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