~ubuntu-branches/ubuntu/natty/libgcrypt11/natty-proposed

« back to all changes in this revision

Viewing changes to src/hmac256.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2009-02-21 13:46:58 UTC
  • mto: (1.1.6 upstream) (2.1.3 squeeze)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20090221134658-855twvcr4ezk2ron
ImportĀ upstreamĀ versionĀ 1.4.4

Show diffs side-by-side

added added

removed removed

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