asm fix for older gcc versions.
[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         return NULL;
430
431       _gcry_hmac256_update (tmphd, hd->opad, 64);
432       _gcry_hmac256_update (tmphd, hd->buf, 32);
433       finalize (tmphd);
434       memcpy (hd->buf, tmphd->buf, 32);
435       _gcry_hmac256_release (tmphd);
436     }
437   if (r_dlen)
438     *r_dlen = 32;
439   return (void*)hd->buf;
440 }
441
442
443 /* Convenience function to compute the HMAC-SHA256 of one file.  The
444    user needs to provide a buffer RESULT of at least 32 bytes, he
445    needs to put the size of the buffer into RESULTSIZE and the
446    FILENAME.  KEY and KEYLEN are as described for _gcry_hmac256_new.
447    On success the function returns the valid length of the result
448    buffer (which will be 32) or -1 on error.  On error ERRNO is set
449    appropriate.  */
450 int
451 _gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
452                     const void *key, size_t keylen)
453 {
454   FILE *fp;
455   hmac256_context_t hd;
456   size_t buffer_size, nread, digestlen;
457   char *buffer;
458   const unsigned char *digest;
459
460   fp = fopen (filename, "rb");
461   if (!fp)
462     return -1;
463
464   hd = _gcry_hmac256_new (key, keylen);
465   if (!hd)
466     {
467       fclose (fp);
468       return -1;
469     }
470
471   buffer_size = 32768;
472   buffer = malloc (buffer_size);
473   if (!buffer)
474     {
475       fclose (fp);
476       _gcry_hmac256_release (hd);
477       return -1;
478     }
479
480   while ( (nread = fread (buffer, 1, buffer_size, fp)))
481     _gcry_hmac256_update (hd, buffer, nread);
482
483   free (buffer);
484
485   if (ferror (fp))
486     {
487       fclose (fp);
488       _gcry_hmac256_release (hd);
489       return -1;
490     }
491
492   fclose (fp);
493
494   digest = _gcry_hmac256_finalize (hd, &digestlen);
495   if (!digest)
496     {
497       _gcry_hmac256_release (hd);
498       return -1;
499     }
500
501   if (digestlen > resultsize)
502     {
503       _gcry_hmac256_release (hd);
504       gpg_err_set_errno (EINVAL);
505       return -1;
506     }
507   memcpy (result, digest, digestlen);
508   _gcry_hmac256_release (hd);
509
510   return digestlen;
511 }
512
513
514
515 #ifdef STANDALONE
516 static int
517 selftest (void)
518 {
519   static struct
520   {
521     const char * const desc;
522     const char * const data;
523     const char * const key;
524     const unsigned char expect[32];
525   } tv[] =
526     {
527       { "data-28 key-4",
528         "what do ya want for nothing?",
529         "Jefe",
530         { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
531           0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
532           0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
533           0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } },
534
535       { "data-9 key-20",
536         "Hi There",
537         "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
538         "\x0b\x0b\x0b\x0b",
539         { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
540           0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
541           0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
542           0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } },
543
544       { "data-50 key-20",
545         "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
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",
549         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
550         "\xaa\xaa\xaa\xaa",
551         { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
552           0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
553           0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
554           0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } },
555
556       { "data-50 key-26",
557         "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
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",
561         "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
562         "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
563         { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
564           0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
565           0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
566           0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } },
567
568       { "data-54 key-131",
569         "Test Using Larger Than Block-Size Key - Hash Key First",
570         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
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",
579         { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
580           0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
581           0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
582           0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } },
583
584       { "data-152 key-131",
585         "This is a test using a larger than block-size key and a larger "
586         "than block-size data. The key needs to be hashed before being "
587         "used by the HMAC algorithm.",
588         "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
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",
597         { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
598           0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
599           0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
600           0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } },
601
602       { NULL }
603     };
604   int tvidx;
605
606   for (tvidx=0; tv[tvidx].desc; tvidx++)
607     {
608       hmac256_context_t hmachd;
609       const unsigned char *digest;
610       size_t dlen;
611
612       hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
613       if (!hmachd)
614         return -1;
615       _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
616       digest = _gcry_hmac256_finalize (hmachd, &dlen);
617       if (!digest)
618         {
619           _gcry_hmac256_release (hmachd);
620           return -1;
621         }
622       if (dlen != sizeof (tv[tvidx].expect)
623           || memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect)))
624         {
625           _gcry_hmac256_release (hmachd);
626           return -1;
627         }
628       _gcry_hmac256_release (hmachd);
629     }
630
631   return 0; /* Succeeded. */
632 }
633
634
635 int
636 main (int argc, char **argv)
637 {
638   const char *pgm;
639   int last_argc = -1;
640   const char *key;
641   size_t keylen;
642   FILE *fp;
643   hmac256_context_t hd;
644   const unsigned char *digest;
645   char buffer[4096];
646   size_t n, dlen, idx;
647   int use_stdin = 0;
648   int use_binary = 0;
649   int use_stdkey = 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       else if (!strcmp (*argv, "--stdkey"))
694         {
695           argc--; argv++;
696           use_stdkey = 1;
697         }
698     }
699
700   if (argc < 1)
701     {
702       fprintf (stderr, "usage: %s [--binary] [--stdkey] key [filename]\n", pgm);
703       exit (1);
704     }
705
706 #ifdef __WIN32
707   if (use_binary)
708     setmode (fileno (stdout), O_BINARY);
709 #endif
710
711   key = use_stdkey? "What am I, a doctor or a moonshuttle conductor?" : *argv;
712   argc--, argv++;
713   keylen = strlen (key);
714   use_stdin = !argc;
715
716   if (selftest ())
717     {
718       fprintf (stderr, "%s: fatal error: self-test failed\n", pgm);
719       exit (2);
720     }
721
722   for (; argc || use_stdin; argv++, argc--)
723     {
724       const char *fname = use_stdin? "-" : *argv;
725       fp = use_stdin? stdin : fopen (fname, "rb");
726       if (!fp)
727         {
728           fprintf (stderr, "%s: can't open `%s': %s\n",
729                    pgm, fname, strerror (errno));
730           exit (1);
731         }
732       hd = _gcry_hmac256_new (key, keylen);
733       if (!hd)
734         {
735           fprintf (stderr, "%s: can't allocate context: %s\n",
736                    pgm, strerror (errno));
737           exit (1);
738         }
739       while ( (n = fread (buffer, 1, sizeof buffer, fp)))
740         _gcry_hmac256_update (hd, buffer, n);
741       if (ferror (fp))
742         {
743           fprintf (stderr, "%s: error reading `%s': %s\n",
744                    pgm, fname, strerror (errno));
745           exit (1);
746         }
747       if (!use_stdin)
748         fclose (fp);
749
750       digest = _gcry_hmac256_finalize (hd, &dlen);
751       if (!digest)
752         {
753           fprintf (stderr, "%s: error computing HMAC: %s\n",
754                    pgm, strerror (errno));
755           exit (1);
756         }
757       if (use_binary)
758         {
759           if (fwrite (digest, dlen, 1, stdout) != 1)
760             {
761               fprintf (stderr, "%s: error writing output: %s\n",
762                        pgm, strerror (errno));
763               exit (1);
764             }
765           if (use_stdin)
766             break;
767         }
768       else
769         {
770           for (idx=0; idx < dlen; idx++)
771             printf ("%02x", digest[idx]);
772           _gcry_hmac256_release (hd);
773           if (use_stdin)
774             {
775               putchar ('\n');
776               break;
777             }
778           printf ("  %s\n", fname);
779         }
780     }
781
782   return 0;
783 }
784 #endif /*STANDALONE*/
785
786
787 /*
788 Local Variables:
789 compile-command: "cc -Wall -g -I.. -DSTANDALONE -o hmac256 hmac256.c"
790 End:
791 */