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