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