A whole bunch of changes to eventually support
[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 implementarion 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
56 #include "hmac256.h"
57
58
59
60 #ifndef HAVE_U32_TYPEDEF
61 # undef u32 /* Undef a possible macro with that name.  */
62 # if SIZEOF_UNSIGNED_INT == 4
63    typedef unsigned int u32;
64 # elif SIZEOF_UNSIGNED_LONG == 4
65    typedef unsigned long u32;
66 # else
67 #  error no typedef for u32
68 # endif
69 # define HAVE_U32_TYPEDEF
70 #endif
71
72
73
74
75 /* The context used by this module.  */
76 struct hmac256_context
77 {
78   u32  h0, h1, h2, h3, h4, h5, h6, h7;
79   u32  nblocks;
80   int  count;
81   int  finalized:1;
82   int  use_hmac:1; 
83   unsigned char buf[64];
84   unsigned char opad[64];
85 };
86
87
88 /* Rotate a 32 bit word.  */
89 #if defined(__GNUC__) && defined(__i386__)
90 static inline u32
91 ror(u32 x, int n)
92 {
93         __asm__("rorl %%cl,%0"
94                 :"=r" (x)
95                 :"0" (x),"c" (n));
96         return x;
97 }
98 #else
99 #define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
100 #endif
101
102 #define my_wipememory2(_ptr,_set,_len) do { \
103               volatile char *_vptr=(volatile char *)(_ptr); \
104               size_t _vlen=(_len); \
105               while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
106                   } while(0)
107 #define my_wipememory(_ptr,_len) my_wipememory2(_ptr,0,_len)
108
109
110
111 \f
112 /* 
113     The SHA-256 core: Transform the message X which consists of 16
114     32-bit-words. See FIPS 180-2 for details.
115  */
116 static void
117 transform (hmac256_context_t hd, const void *data_arg)
118 {
119   const unsigned char *data = data_arg;
120
121 #define Cho(x,y,z) (z ^ (x & (y ^ z)))      /* (4.2) same as SHA-1's F1 */
122 #define Maj(x,y,z) ((x & y) | (z & (x|y)))  /* (4.3) same as SHA-1's F3 */
123 #define Sum0(x) (ror ((x), 2) ^ ror ((x), 13) ^ ror ((x), 22))  /* (4.4) */
124 #define Sum1(x) (ror ((x), 6) ^ ror ((x), 11) ^ ror ((x), 25))  /* (4.5) */
125 #define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3))       /* (4.6) */
126 #define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10))     /* (4.7) */
127 #define R(a,b,c,d,e,f,g,h,k,w) do                                 \
128           {                                                       \
129             t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w);  \
130             t2 = Sum0((a)) + Maj((a),(b),(c));                    \
131             h = g;                                                \
132             g = f;                                                \
133             f = e;                                                \
134             e = d + t1;                                           \
135             d = c;                                                \
136             c = b;                                                \
137             b = a;                                                \
138             a = t1 + t2;                                          \
139           } while (0)
140  
141   static const u32 K[64] = 
142     {
143       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
144       0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
145       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
146       0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 
147       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
148       0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
149       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
150       0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
151       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
152       0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
153       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
154       0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
155       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
156       0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
157       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
158       0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
159     };
160
161   u32 a, b, c, d, e, f, g, h, t1, t2;
162   u32 x[16];
163   u32 w[64];
164   int i;
165   
166   a = hd->h0;
167   b = hd->h1;
168   c = hd->h2;
169   d = hd->h3;
170   e = hd->h4;
171   f = hd->h5;
172   g = hd->h6;
173   h = hd->h7;
174   
175 #ifdef WORDS_BIGENDIAN
176   memcpy (x, data, 64);
177 #else /*!WORDS_BIGENDIAN*/
178   { 
179     unsigned char *p2;
180   
181     for (i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 ) 
182       {
183         p2[3] = *data++;
184         p2[2] = *data++;
185         p2[1] = *data++;
186         p2[0] = *data++;
187       }
188   }
189 #endif /*!WORDS_BIGENDIAN*/
190
191   for (i=0; i < 16; i++)
192     w[i] = x[i];
193   for (; i < 64; i++)
194     w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16];
195
196   for (i=0; i < 64; i++)
197     R(a,b,c,d,e,f,g,h,K[i],w[i]);
198
199   hd->h0 += a;
200   hd->h1 += b;
201   hd->h2 += c;
202   hd->h3 += d;
203   hd->h4 += e;
204   hd->h5 += f;
205   hd->h6 += g;
206   hd->h7 += h;
207 }
208 #undef Cho
209 #undef Maj
210 #undef Sum0
211 #undef Sum1
212 #undef S0
213 #undef S1
214 #undef R
215
216
217 /*  Finalize the current SHA256 calculation.  */
218 static void
219 finalize (hmac256_context_t hd)
220 {
221   u32 t, msb, lsb;
222   unsigned char *p;
223   
224   if (hd->finalized)
225     return; /* Silently ignore a finalized context.  */
226
227   _gcry_hmac256_update (hd, NULL, 0); /* Flush.  */
228
229   t = hd->nblocks;
230   /* Multiply by 64 to make a byte count. */
231   lsb = t << 6;
232   msb = t >> 26;
233   /* Add the count. */
234   t = lsb;
235   if ((lsb += hd->count) < t)
236     msb++;
237   /* Multiply by 8 to make a bit count. */
238   t = lsb;
239   lsb <<= 3;
240   msb <<= 3;
241   msb |= t >> 29;
242
243   if (hd->count < 56)
244     { /* Enough room.  */
245       hd->buf[hd->count++] = 0x80; /* pad */
246       while (hd->count < 56)
247         hd->buf[hd->count++] = 0;  /* pad */
248     }
249   else
250     { /* Need one extra block. */
251       hd->buf[hd->count++] = 0x80; /* pad character */
252       while (hd->count < 64)
253         hd->buf[hd->count++] = 0;
254       _gcry_hmac256_update (hd, NULL, 0);  /* Flush.  */;
255       memset (hd->buf, 0, 56 ); /* Zero out next next block.  */
256     }
257   /* Append the 64 bit count. */
258   hd->buf[56] = msb >> 24;
259   hd->buf[57] = msb >> 16;
260   hd->buf[58] = msb >>  8;
261   hd->buf[59] = msb;
262   hd->buf[60] = lsb >> 24;
263   hd->buf[61] = lsb >> 16;
264   hd->buf[62] = lsb >>  8;
265   hd->buf[63] = lsb;
266   transform (hd, hd->buf);
267
268   /* Store the digest into hd->buf.  */
269   p = hd->buf;
270 #ifdef WORDS_BIGENDIAN
271 #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
272 #else /* little endian */
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 #endif
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 fucntion 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       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 #ifdef STANDALONE
445 static int
446 selftest (void)
447 {
448   static struct 
449   {
450     const char * const desc;
451     const char * const data;
452     const char * const key;
453     const char const expect[32];
454   } tv[] =
455     {
456       { "data-28 key-4",
457         "what do ya want for nothing?", 
458         "Jefe",
459         { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
460           0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
461           0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
462           0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } },
463
464       { "data-9 key-20",
465         "Hi There",
466         "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
467         "\x0b\x0b\x0b\x0b",
468         { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
469           0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
470           0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
471           0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } },
472
473       { "data-50 key-20",
474         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
475         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
476         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
477         "\xdd\xdd",
478         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
479         "\xaa\xaa\xaa\xaa",
480         { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
481           0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
482           0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
483           0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } },
484
485       { "data-50 key-26",
486         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
487         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
488         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
489         "\xcd\xcd",
490         "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
491         "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
492         { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
493           0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
494           0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
495           0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } },
496
497       { "data-54 key-131",
498         "Test Using Larger Than Block-Size Key - Hash Key First",
499         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
500         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
501         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
502         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
503         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
504         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
505         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
506         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
507         "\xaa\xaa\xaa",
508         { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
509           0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
510           0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
511           0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } },
512
513       { "data-152 key-131",
514         "This is a test using a larger than block-size key and a larger "
515         "than block-size data. The key needs to be hashed before being "
516         "used by the HMAC algorithm.",
517         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
518         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
519         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
520         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
521         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
522         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
523         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
524         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
525         "\xaa\xaa\xaa",
526         { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
527           0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
528           0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
529           0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } },
530
531       { NULL }
532     };
533   int tvidx;
534   
535   for (tvidx=0; tv[tvidx].desc; tvidx++)
536     {
537       hmac256_context_t hmachd;
538       const unsigned char *digest;
539       size_t dlen;
540
541       hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
542       if (!hmachd)
543         return -1;
544       _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
545       digest = _gcry_hmac256_finalize (hmachd, &dlen);
546       if (!digest)
547         {
548           _gcry_hmac256_release (hmachd);
549           return -1;
550         }
551       if (dlen != sizeof (tv[tvidx].expect)
552           || memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect)))
553         {
554           _gcry_hmac256_release (hmachd);
555           return -1;
556         }
557       _gcry_hmac256_release (hmachd);
558     }
559   
560   return 0; /* Succeeded. */
561 }
562
563
564 int 
565 main (int argc, char **argv)
566 {
567   const char *pgm;
568   int last_argc = -1;
569   const char *key;
570   size_t keylen;
571   FILE *fp;
572   hmac256_context_t hd;
573   const unsigned char *digest;
574   char buffer[4096];
575   size_t n, dlen, idx;
576   int use_stdin = 0;
577
578   assert (sizeof (u32) == 4);
579
580   if (argc)
581     {
582       pgm = strrchr (*argv, '/');
583       if (pgm)
584         pgm++;
585       else
586         pgm = *argv;
587       argc--; argv++;
588     }
589   else
590     pgm = "?";
591
592   while (argc && last_argc != argc )
593     {
594       last_argc = argc;
595       if (!strcmp (*argv, "--"))
596         {
597           argc--; argv++;
598           break;
599         }
600       else if (!strcmp (*argv, "--version"))
601         {
602           fputs ("hmac256 (Libgcrypt) " VERSION "\n"
603                  "Copyright (C) 2008 Free Software Foundation, Inc.\n"
604                  "License LGPLv2.1+: GNU LGPL version 2.1 or later "
605                  "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
606                  "This is free software: you are free to change and "
607                  "redistribute it.\n"
608                  "There is NO WARRANTY, to the extent permitted by law.\n",
609                  stdout);
610           exit (0);
611         }
612     }          
613
614   if (argc < 1)
615     {
616       fprintf (stderr, "usage: %s key [filename]\n", pgm);
617       exit (1);
618     }
619
620
621   key = *argv;
622   argc--, argv++;
623   keylen = strlen (key);
624   use_stdin = !argc;
625
626   if (selftest ())
627     {
628       fprintf (stderr, "%s: fatal error: self-test failed\n", pgm);
629       exit (2);
630     }
631
632   for (; argc || use_stdin; argv++, argc--)
633     {
634       const char *fname = use_stdin? "-" : *argv;
635       fp = use_stdin? stdin : fopen (fname, "rb");
636       if (!fp)
637         {
638           fprintf (stderr, "%s: can't open `%s': %s\n", 
639                    pgm, fname, strerror (errno));
640           exit (1);
641         }
642       hd = _gcry_hmac256_new (key, keylen);
643       if (!hd)
644         {
645           fprintf (stderr, "%s: can't allocate context: %s\n", 
646                    pgm, strerror (errno));
647           exit (1);
648         }
649       while ( (n = fread (buffer, 1, sizeof buffer, fp)))
650         _gcry_hmac256_update (hd, buffer, n);
651       if (ferror (fp))
652         {
653           fprintf (stderr, "%s: error reading `%s': %s\n", 
654                    pgm, fname, strerror (errno));
655           exit (1);
656         }
657       if (!use_stdin)
658         fclose (fp);
659
660       digest = _gcry_hmac256_finalize (hd, &dlen);
661       if (!digest)
662         {
663           fprintf (stderr, "%s: error computing HMAC: %s\n",
664                    pgm, strerror (errno));
665           exit (1);
666         }
667       for (idx=0; idx < dlen; idx++)
668         printf ("%02x", digest[idx]);
669       _gcry_hmac256_release (hd);
670       if (use_stdin)
671         {
672           putchar ('\n');
673           break;
674         }
675       printf ("  %s\n", fname);
676     }
677
678   return 0;
679 }
680 #endif /*STANDALONE*/
681
682
683 /*
684 Local Variables:
685 compile-command: "cc -Wall -g -I.. -DSTANDALONE -o hmac256 hmac256.c"
686 End:
687 */