Remove duplicated prototypes.
[libgcrypt.git] / src / hmac256.c
1 /* hmac256.c - Standalone HMAC implementation
2  * Copyright (C) 2003, 2006, 2008  Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21     This is a standalone HMAC-SHA-256 implementation based on the code
22     from ../cipher/sha256.c.  It is a second implementation to allow
23     comparing against the standard implementations and to be used for
24     internal consistency checks.  It should not be used for sensitive
25     data because no mechanisms to clear the stack etc are used.
26
27     This module may be used standalone and requires only a few
28     standard definitions to be provided in a config.h file.
29
30     Types:
31
32      u32 - unsigned 32 bit type.
33
34     Constants:
35
36      WORDS_BIGENDIAN       Defined to 1 on big endian systems.
37      inline                If defined, it should yield the keyword used
38                            to inline a function.
39      HAVE_U32_TYPEDEF      Defined if the u32 type is available.
40      SIZEOF_UNSIGNED_INT   Defined to the size in bytes of an unsigned int.
41      SIZEOF_UNSIGNED_LONG  Defined to the size in bytes of an unsigned long.
42
43      STANDALONE            Compile a test driver similar to the
44                            sha1sum tool.  This driver uses a self-test
45                            identically to the one used by Libcgrypt
46                            for testing this included module.
47  */
48
49 #include <config.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <assert.h>
54 #include <errno.h>
55 #if defined(__WIN32) && defined(STANDALONE)
56 # include <fcntl.h> /* We need setmode().  */
57 #endif
58
59 /* For a native WindowsCE binary we need to include gpg-error.h to
60    provide a replacement for strerror.  In other cases we need a
61    replacement macro for gpg_err_set_errno.  */
62 #ifdef __MINGW32CE__
63 # include <gpg-error.h>
64 #else
65 # define gpg_err_set_errno(a) (errno = (a))
66 #endif
67
68 #include "hmac256.h"
69
70
71
72 #ifndef HAVE_U32_TYPEDEF
73 # undef u32 /* Undef a possible macro with that name.  */
74 # if SIZEOF_UNSIGNED_INT == 4
75    typedef unsigned int u32;
76 # elif SIZEOF_UNSIGNED_LONG == 4
77    typedef unsigned long u32;
78 # else
79 #  error no typedef for u32
80 # endif
81 # define HAVE_U32_TYPEDEF
82 #endif
83
84
85
86
87 /* The context used by this module.  */
88 struct hmac256_context
89 {
90   u32  h0, h1, h2, h3, h4, h5, h6, h7;
91   u32  nblocks;
92   int  count;
93   int  finalized:1;
94   int  use_hmac:1;
95   unsigned char buf[64];
96   unsigned char opad[64];
97 };
98
99
100 /* Rotate a 32 bit word.  */
101 static inline u32 ror(u32 x, int n)
102 {
103         return ( ((x) >> (n)) | ((x) << (32-(n))) );
104 }
105
106 #define my_wipememory2(_ptr,_set,_len) do { \
107               volatile char *_vptr=(volatile char *)(_ptr); \
108               size_t _vlen=(_len); \
109               while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
110                   } while(0)
111 #define my_wipememory(_ptr,_len) my_wipememory2(_ptr,0,_len)
112
113
114
115 \f
116 /*
117     The SHA-256 core: Transform the message X which consists of 16
118     32-bit-words. See FIPS 180-2 for details.
119  */
120 static void
121 transform (hmac256_context_t hd, const void *data_arg)
122 {
123   const unsigned char *data = data_arg;
124
125 #define Cho(x,y,z) (z ^ (x & (y ^ z)))      /* (4.2) same as SHA-1's F1 */
126 #define Maj(x,y,z) ((x & y) | (z & (x|y)))  /* (4.3) same as SHA-1's F3 */
127 #define Sum0(x) (ror ((x), 2) ^ ror ((x), 13) ^ ror ((x), 22))  /* (4.4) */
128 #define Sum1(x) (ror ((x), 6) ^ ror ((x), 11) ^ ror ((x), 25))  /* (4.5) */
129 #define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3))       /* (4.6) */
130 #define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10))     /* (4.7) */
131 #define R(a,b,c,d,e,f,g,h,k,w) do                                 \
132           {                                                       \
133             t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w);  \
134             t2 = Sum0((a)) + Maj((a),(b),(c));                    \
135             h = g;                                                \
136             g = f;                                                \
137             f = e;                                                \
138             e = d + t1;                                           \
139             d = c;                                                \
140             c = b;                                                \
141             b = a;                                                \
142             a = t1 + t2;                                          \
143           } while (0)
144
145   static const u32 K[64] =
146     {
147       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
148       0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
149       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
150       0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
151       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
152       0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
153       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
154       0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
155       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
156       0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
157       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
158       0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
159       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
160       0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
161       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
162       0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
163     };
164
165   u32 a, b, c, d, e, f, g, h, t1, t2;
166   u32 x[16];
167   u32 w[64];
168   int i;
169
170   a = hd->h0;
171   b = hd->h1;
172   c = hd->h2;
173   d = hd->h3;
174   e = hd->h4;
175   f = hd->h5;
176   g = hd->h6;
177   h = hd->h7;
178
179 #ifdef WORDS_BIGENDIAN
180   memcpy (x, data, 64);
181 #else /*!WORDS_BIGENDIAN*/
182   {
183     unsigned char *p2;
184
185     for (i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 )
186       {
187         p2[3] = *data++;
188         p2[2] = *data++;
189         p2[1] = *data++;
190         p2[0] = *data++;
191       }
192   }
193 #endif /*!WORDS_BIGENDIAN*/
194
195   for (i=0; i < 16; i++)
196     w[i] = x[i];
197   for (; i < 64; i++)
198     w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16];
199
200   for (i=0; i < 64; i++)
201     R(a,b,c,d,e,f,g,h,K[i],w[i]);
202
203   hd->h0 += a;
204   hd->h1 += b;
205   hd->h2 += c;
206   hd->h3 += d;
207   hd->h4 += e;
208   hd->h5 += f;
209   hd->h6 += g;
210   hd->h7 += h;
211 }
212 #undef Cho
213 #undef Maj
214 #undef Sum0
215 #undef Sum1
216 #undef S0
217 #undef S1
218 #undef R
219
220
221 /*  Finalize the current SHA256 calculation.  */
222 static void
223 finalize (hmac256_context_t hd)
224 {
225   u32 t, msb, lsb;
226   unsigned char *p;
227
228   if (hd->finalized)
229     return; /* Silently ignore a finalized context.  */
230
231   _gcry_hmac256_update (hd, NULL, 0); /* Flush.  */
232
233   t = hd->nblocks;
234   /* Multiply by 64 to make a byte count. */
235   lsb = t << 6;
236   msb = t >> 26;
237   /* Add the count. */
238   t = lsb;
239   if ((lsb += hd->count) < t)
240     msb++;
241   /* Multiply by 8 to make a bit count. */
242   t = lsb;
243   lsb <<= 3;
244   msb <<= 3;
245   msb |= t >> 29;
246
247   if (hd->count < 56)
248     { /* Enough room.  */
249       hd->buf[hd->count++] = 0x80; /* pad */
250       while (hd->count < 56)
251         hd->buf[hd->count++] = 0;  /* pad */
252     }
253   else
254     { /* Need one extra block. */
255       hd->buf[hd->count++] = 0x80; /* pad character */
256       while (hd->count < 64)
257         hd->buf[hd->count++] = 0;
258       _gcry_hmac256_update (hd, NULL, 0);  /* Flush.  */;
259       memset (hd->buf, 0, 56 ); /* Zero out next next block.  */
260     }
261   /* Append the 64 bit count. */
262   hd->buf[56] = msb >> 24;
263   hd->buf[57] = msb >> 16;
264   hd->buf[58] = msb >>  8;
265   hd->buf[59] = msb;
266   hd->buf[60] = lsb >> 24;
267   hd->buf[61] = lsb >> 16;
268   hd->buf[62] = lsb >>  8;
269   hd->buf[63] = lsb;
270   transform (hd, hd->buf);
271
272   /* Store the digest into hd->buf.  */
273   p = hd->buf;
274 #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;  \
275                   *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
276   X(0);
277   X(1);
278   X(2);
279   X(3);
280   X(4);
281   X(5);
282   X(6);
283   X(7);
284 #undef X
285   hd->finalized = 1;
286 }
287
288
289
290 /* Create a new context.  On error NULL is returned and errno is set
291    appropriately.  If KEY is given the function computes HMAC using
292    this key; with KEY given as NULL, a plain SHA-256 digest is
293    computed.  */
294 hmac256_context_t
295 _gcry_hmac256_new (const void *key, size_t keylen)
296 {
297   hmac256_context_t hd;
298
299   hd = malloc (sizeof *hd);
300   if (!hd)
301     return NULL;
302
303   hd->h0 = 0x6a09e667;
304   hd->h1 = 0xbb67ae85;
305   hd->h2 = 0x3c6ef372;
306   hd->h3 = 0xa54ff53a;
307   hd->h4 = 0x510e527f;
308   hd->h5 = 0x9b05688c;
309   hd->h6 = 0x1f83d9ab;
310   hd->h7 = 0x5be0cd19;
311   hd->nblocks = 0;
312   hd->count = 0;
313   hd->finalized = 0;
314   hd->use_hmac = 0;
315
316   if (key)
317     {
318       int i;
319       unsigned char ipad[64];
320
321       memset (ipad, 0, 64);
322       memset (hd->opad, 0, 64);
323       if (keylen <= 64)
324         {
325           memcpy (ipad, key, keylen);
326           memcpy (hd->opad, key, keylen);
327         }
328       else
329         {
330           hmac256_context_t tmphd;
331
332           tmphd = _gcry_hmac256_new (NULL, 0);
333           if (!tmphd)
334             {
335               free (hd);
336               return NULL;
337             }
338           _gcry_hmac256_update (tmphd, key, keylen);
339           finalize (tmphd);
340           memcpy (ipad, tmphd->buf, 32);
341           memcpy (hd->opad, tmphd->buf, 32);
342           _gcry_hmac256_release (tmphd);
343         }
344       for (i=0; i < 64; i++)
345         {
346           ipad[i] ^= 0x36;
347           hd->opad[i] ^= 0x5c;
348         }
349       hd->use_hmac = 1;
350       _gcry_hmac256_update (hd, ipad, 64);
351       my_wipememory (ipad, 64);
352     }
353
354   return hd;
355 }
356
357 /* Release a context created by _gcry_hmac256_new.  CTX may be NULL
358    in which case the function does nothing.  */
359 void
360 _gcry_hmac256_release (hmac256_context_t ctx)
361 {
362   if (ctx)
363     {
364       /* Note: We need to take care not to modify errno.  */
365       if (ctx->use_hmac)
366         my_wipememory (ctx->opad, 64);
367       free (ctx);
368     }
369 }
370
371
372 /* Update the message digest with the contents of BUFFER containing
373    LENGTH bytes.  */
374 void
375 _gcry_hmac256_update (hmac256_context_t hd,
376                         const void *buffer, size_t length)
377 {
378   const unsigned char *inbuf = buffer;
379
380   if (hd->finalized)
381     return; /* Silently ignore a finalized context.  */
382
383   if (hd->count == 64)
384     {
385       /* Flush the buffer. */
386       transform (hd, hd->buf);
387       hd->count = 0;
388       hd->nblocks++;
389     }
390   if (!inbuf)
391     return;  /* Only flushing was requested. */
392   if (hd->count)
393     {
394       for (; length && hd->count < 64; length--)
395         hd->buf[hd->count++] = *inbuf++;
396       _gcry_hmac256_update (hd, NULL, 0); /* Flush.  */
397       if (!length)
398         return;
399     }
400
401
402   while (length >= 64)
403     {
404       transform (hd, inbuf);
405       hd->count = 0;
406       hd->nblocks++;
407       length -= 64;
408       inbuf += 64;
409     }
410   for (; length && hd->count < 64; length--)
411     hd->buf[hd->count++] = *inbuf++;
412 }
413
414
415 /* Finalize an operation and return the digest.  If R_DLEN is not NULL
416    the length of the digest will be stored at that address.  The
417    returned value is valid as long as the context exists.  On error
418    NULL is returned. */
419 const void *
420 _gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen)
421 {
422   finalize (hd);
423   if (hd->use_hmac)
424     {
425       hmac256_context_t tmphd;
426
427       tmphd = _gcry_hmac256_new (NULL, 0);
428       if (!tmphd)
429         {
430           free (hd);
431           return NULL;
432         }
433       _gcry_hmac256_update (tmphd, hd->opad, 64);
434       _gcry_hmac256_update (tmphd, hd->buf, 32);
435       finalize (tmphd);
436       memcpy (hd->buf, tmphd->buf, 32);
437       _gcry_hmac256_release (tmphd);
438     }
439   if (r_dlen)
440     *r_dlen = 32;
441   return (void*)hd->buf;
442 }
443
444
445 /* Convenience function to compute the HMAC-SHA256 of one file.  The
446    user needs to provide a buffer RESULT of at least 32 bytes, he
447    needs to put the size of the buffer into RESULTSIZE and the
448    FILENAME.  KEY and KEYLEN are as described for _gcry_hmac256_new.
449    On success the function returns the valid length of the result
450    buffer (which will be 32) or -1 on error.  On error ERRNO is set
451    appropriate.  */
452 int
453 _gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
454                     const void *key, size_t keylen)
455 {
456   FILE *fp;
457   hmac256_context_t hd;
458   size_t buffer_size, nread, digestlen;
459   char *buffer;
460   const unsigned char *digest;
461
462   fp = fopen (filename, "rb");
463   if (!fp)
464     return -1;
465
466   hd = _gcry_hmac256_new (key, keylen);
467   if (!hd)
468     {
469       fclose (fp);
470       return -1;
471     }
472
473   buffer_size = 32768;
474   buffer = malloc (buffer_size);
475   if (!buffer)
476     {
477       fclose (fp);
478       _gcry_hmac256_release (hd);
479       return -1;
480     }
481
482   while ( (nread = fread (buffer, 1, buffer_size, fp)))
483     _gcry_hmac256_update (hd, buffer, nread);
484
485   free (buffer);
486
487   if (ferror (fp))
488     {
489       fclose (fp);
490       _gcry_hmac256_release (hd);
491       return -1;
492     }
493
494   fclose (fp);
495
496   digest = _gcry_hmac256_finalize (hd, &digestlen);
497   if (!digest)
498     {
499       _gcry_hmac256_release (hd);
500       return -1;
501     }
502
503   if (digestlen > resultsize)
504     {
505       _gcry_hmac256_release (hd);
506       gpg_err_set_errno (EINVAL);
507       return -1;
508     }
509   memcpy (result, digest, digestlen);
510   _gcry_hmac256_release (hd);
511
512   return digestlen;
513 }
514
515
516
517 #ifdef STANDALONE
518 static int
519 selftest (void)
520 {
521   static struct
522   {
523     const char * const desc;
524     const char * const data;
525     const char * const key;
526     const unsigned char expect[32];
527   } tv[] =
528     {
529       { "data-28 key-4",
530         "what do ya want for nothing?",
531         "Jefe",
532         { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
533           0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
534           0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
535           0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } },
536
537       { "data-9 key-20",
538         "Hi There",
539         "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
540         "\x0b\x0b\x0b\x0b",
541         { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
542           0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
543           0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
544           0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } },
545
546       { "data-50 key-20",
547         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
548         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
549         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
550         "\xdd\xdd",
551         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
552         "\xaa\xaa\xaa\xaa",
553         { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
554           0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
555           0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
556           0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } },
557
558       { "data-50 key-26",
559         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
560         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
561         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
562         "\xcd\xcd",
563         "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
564         "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
565         { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
566           0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
567           0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
568           0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } },
569
570       { "data-54 key-131",
571         "Test Using Larger Than Block-Size Key - Hash Key First",
572         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
573         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
574         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
575         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
576         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
577         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
578         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
579         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
580         "\xaa\xaa\xaa",
581         { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
582           0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
583           0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
584           0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } },
585
586       { "data-152 key-131",
587         "This is a test using a larger than block-size key and a larger "
588         "than block-size data. The key needs to be hashed before being "
589         "used by the HMAC algorithm.",
590         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
591         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
592         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
593         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
594         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
595         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
596         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
597         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
598         "\xaa\xaa\xaa",
599         { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
600           0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
601           0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
602           0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } },
603
604       { NULL }
605     };
606   int tvidx;
607
608   for (tvidx=0; tv[tvidx].desc; tvidx++)
609     {
610       hmac256_context_t hmachd;
611       const unsigned char *digest;
612       size_t dlen;
613
614       hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
615       if (!hmachd)
616         return -1;
617       _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
618       digest = _gcry_hmac256_finalize (hmachd, &dlen);
619       if (!digest)
620         {
621           _gcry_hmac256_release (hmachd);
622           return -1;
623         }
624       if (dlen != sizeof (tv[tvidx].expect)
625           || memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect)))
626         {
627           _gcry_hmac256_release (hmachd);
628           return -1;
629         }
630       _gcry_hmac256_release (hmachd);
631     }
632
633   return 0; /* Succeeded. */
634 }
635
636
637 int
638 main (int argc, char **argv)
639 {
640   const char *pgm;
641   int last_argc = -1;
642   const char *key;
643   size_t keylen;
644   FILE *fp;
645   hmac256_context_t hd;
646   const unsigned char *digest;
647   char buffer[4096];
648   size_t n, dlen, idx;
649   int use_stdin = 0;
650   int use_binary = 0;
651
652   assert (sizeof (u32) == 4);
653 #ifdef __WIN32
654   setmode (fileno (stdin), O_BINARY);
655 #endif
656
657   if (argc)
658     {
659       pgm = strrchr (*argv, '/');
660       if (pgm)
661         pgm++;
662       else
663         pgm = *argv;
664       argc--; argv++;
665     }
666   else
667     pgm = "?";
668
669   while (argc && last_argc != argc )
670     {
671       last_argc = argc;
672       if (!strcmp (*argv, "--"))
673         {
674           argc--; argv++;
675           break;
676         }
677       else if (!strcmp (*argv, "--version"))
678         {
679           fputs ("hmac256 (Libgcrypt) " VERSION "\n"
680                  "Copyright (C) 2008 Free Software Foundation, Inc.\n"
681                  "License LGPLv2.1+: GNU LGPL version 2.1 or later "
682                  "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
683                  "This is free software: you are free to change and "
684                  "redistribute it.\n"
685                  "There is NO WARRANTY, to the extent permitted by law.\n",
686                  stdout);
687           exit (0);
688         }
689       else if (!strcmp (*argv, "--binary"))
690         {
691           argc--; argv++;
692           use_binary = 1;
693         }
694     }
695
696   if (argc < 1)
697     {
698       fprintf (stderr, "usage: %s [--binary] key [filename]\n", pgm);
699       exit (1);
700     }
701
702 #ifdef __WIN32
703   if (use_binary)
704     setmode (fileno (stdout), O_BINARY);
705 #endif
706
707   key = *argv;
708   argc--, argv++;
709   keylen = strlen (key);
710   use_stdin = !argc;
711
712   if (selftest ())
713     {
714       fprintf (stderr, "%s: fatal error: self-test failed\n", pgm);
715       exit (2);
716     }
717
718   for (; argc || use_stdin; argv++, argc--)
719     {
720       const char *fname = use_stdin? "-" : *argv;
721       fp = use_stdin? stdin : fopen (fname, "rb");
722       if (!fp)
723         {
724           fprintf (stderr, "%s: can't open `%s': %s\n",
725                    pgm, fname, strerror (errno));
726           exit (1);
727         }
728       hd = _gcry_hmac256_new (key, keylen);
729       if (!hd)
730         {
731           fprintf (stderr, "%s: can't allocate context: %s\n",
732                    pgm, strerror (errno));
733           exit (1);
734         }
735       while ( (n = fread (buffer, 1, sizeof buffer, fp)))
736         _gcry_hmac256_update (hd, buffer, n);
737       if (ferror (fp))
738         {
739           fprintf (stderr, "%s: error reading `%s': %s\n",
740                    pgm, fname, strerror (errno));
741           exit (1);
742         }
743       if (!use_stdin)
744         fclose (fp);
745
746       digest = _gcry_hmac256_finalize (hd, &dlen);
747       if (!digest)
748         {
749           fprintf (stderr, "%s: error computing HMAC: %s\n",
750                    pgm, strerror (errno));
751           exit (1);
752         }
753       if (use_binary)
754         {
755           if (fwrite (digest, dlen, 1, stdout) != 1)
756             {
757               fprintf (stderr, "%s: error writing output: %s\n",
758                        pgm, strerror (errno));
759               exit (1);
760             }
761           if (use_stdin)
762             break;
763         }
764       else
765         {
766           for (idx=0; idx < dlen; idx++)
767             printf ("%02x", digest[idx]);
768           _gcry_hmac256_release (hd);
769           if (use_stdin)
770             {
771               putchar ('\n');
772               break;
773             }
774           printf ("  %s\n", fname);
775         }
776     }
777
778   return 0;
779 }
780 #endif /*STANDALONE*/
781
782
783 /*
784 Local Variables:
785 compile-command: "cc -Wall -g -I.. -DSTANDALONE -o hmac256 hmac256.c"
786 End:
787 */