1
/* hmac256.c - Standalone HMAC implementation
2
* Copyright (C) 2003, 2006, 2008 Free Software Foundation, Inc.
4
* This file is part of Libgcrypt.
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.
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.
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/>.
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.
27
This module may be used standalone and requires only a few
28
standard definitions to be provided in a config.h file.
32
u32 - unsigned 32 bit type.
36
WORDS_BIGENDIAN Defined to 1 on big endian systems.
37
inline If defined, it should yield the keyword used
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.
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.
55
#if defined(__WIN32) && defined(STANDALONE)
56
# include <fcntl.h> /* We need setmode(). */
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;
70
# error no typedef for u32
72
# define HAVE_U32_TYPEDEF
78
/* The context used by this module. */
79
struct hmac256_context
81
u32 h0, h1, h2, h3, h4, h5, h6, h7;
86
unsigned char buf[64];
87
unsigned char opad[64];
91
/* Rotate a 32 bit word. */
92
#if defined(__GNUC__) && defined(__i386__)
96
__asm__("rorl %%cl,%0"
102
#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
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--; } \
110
#define my_wipememory(_ptr,_len) my_wipememory2(_ptr,0,_len)
116
The SHA-256 core: Transform the message X which consists of 16
117
32-bit-words. See FIPS 180-2 for details.
120
transform (hmac256_context_t hd, const void *data_arg)
122
const unsigned char *data = data_arg;
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 \
132
t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \
133
t2 = Sum0((a)) + Maj((a),(b),(c)); \
144
static const u32 K[64] =
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
164
u32 a, b, c, d, e, f, g, h, t1, t2;
178
#ifdef WORDS_BIGENDIAN
179
memcpy (x, data, 64);
180
#else /*!WORDS_BIGENDIAN*/
184
for (i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 )
192
#endif /*!WORDS_BIGENDIAN*/
194
for (i=0; i < 16; i++)
197
w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16];
199
for (i=0; i < 64; i++)
200
R(a,b,c,d,e,f,g,h,K[i],w[i]);
220
/* Finalize the current SHA256 calculation. */
222
finalize (hmac256_context_t hd)
228
return; /* Silently ignore a finalized context. */
230
_gcry_hmac256_update (hd, NULL, 0); /* Flush. */
233
/* Multiply by 64 to make a byte count. */
238
if ((lsb += hd->count) < t)
240
/* Multiply by 8 to make a bit count. */
248
hd->buf[hd->count++] = 0x80; /* pad */
249
while (hd->count < 56)
250
hd->buf[hd->count++] = 0; /* pad */
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. */
260
/* Append the 64 bit count. */
261
hd->buf[56] = msb >> 24;
262
hd->buf[57] = msb >> 16;
263
hd->buf[58] = msb >> 8;
265
hd->buf[60] = lsb >> 24;
266
hd->buf[61] = lsb >> 16;
267
hd->buf[62] = lsb >> 8;
269
transform (hd, hd->buf);
271
/* Store the digest into 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)
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
294
_gcry_hmac256_new (const void *key, size_t keylen)
296
hmac256_context_t hd;
298
hd = malloc (sizeof *hd);
318
unsigned char ipad[64];
320
memset (ipad, 0, 64);
321
memset (hd->opad, 0, 64);
324
memcpy (ipad, key, keylen);
325
memcpy (hd->opad, key, keylen);
329
hmac256_context_t tmphd;
331
tmphd = _gcry_hmac256_new (NULL, 0);
337
_gcry_hmac256_update (tmphd, key, keylen);
339
memcpy (ipad, tmphd->buf, 32);
340
memcpy (hd->opad, tmphd->buf, 32);
341
_gcry_hmac256_release (tmphd);
343
for (i=0; i < 64; i++)
349
_gcry_hmac256_update (hd, ipad, 64);
350
my_wipememory (ipad, 64);
356
/* Release a context created by _gcry_hmac256_new. CTX may be NULL
357
in which case the function does nothing. */
359
_gcry_hmac256_release (hmac256_context_t ctx)
363
/* Note: We need to take care not to modify errno. */
365
my_wipememory (ctx->opad, 64);
371
/* Update the message digest with the contents of BUFFER containing
374
_gcry_hmac256_update (hmac256_context_t hd,
375
const void *buffer, size_t length)
377
const unsigned char *inbuf = buffer;
380
return; /* Silently ignore a finalized context. */
384
/* Flush the buffer. */
385
transform (hd, hd->buf);
390
return; /* Only flushing was requested. */
393
for (; length && hd->count < 64; length--)
394
hd->buf[hd->count++] = *inbuf++;
395
_gcry_hmac256_update (hd, NULL, 0); /* Flush. */
403
transform (hd, inbuf);
409
for (; length && hd->count < 64; length--)
410
hd->buf[hd->count++] = *inbuf++;
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
419
_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen)
424
hmac256_context_t tmphd;
426
tmphd = _gcry_hmac256_new (NULL, 0);
432
_gcry_hmac256_update (tmphd, hd->opad, 64);
433
_gcry_hmac256_update (tmphd, hd->buf, 32);
435
memcpy (hd->buf, tmphd->buf, 32);
436
_gcry_hmac256_release (tmphd);
440
return (void*)hd->buf;
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
452
_gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
453
const void *key, size_t keylen)
456
hmac256_context_t hd;
457
size_t buffer_size, nread, digestlen;
459
const unsigned char *digest;
461
fp = fopen (filename, "rb");
465
hd = _gcry_hmac256_new (key, keylen);
473
buffer = malloc (buffer_size);
477
_gcry_hmac256_release (hd);
481
while ( (nread = fread (buffer, 1, buffer_size, fp)))
482
_gcry_hmac256_update (hd, buffer, nread);
489
_gcry_hmac256_release (hd);
495
digest = _gcry_hmac256_finalize (hd, &digestlen);
498
_gcry_hmac256_release (hd);
502
if (digestlen > resultsize)
504
_gcry_hmac256_release (hd);
508
memcpy (result, digest, digestlen);
509
_gcry_hmac256_release (hd);
522
const char * const desc;
523
const char * const data;
524
const char * const key;
525
const unsigned char expect[32];
529
"what do ya want for nothing?",
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 } },
538
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\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 } },
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"
550
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\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 } },
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"
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 } },
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"
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 } },
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"
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 } },
607
for (tvidx=0; tv[tvidx].desc; tvidx++)
609
hmac256_context_t hmachd;
610
const unsigned char *digest;
613
hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
616
_gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
617
digest = _gcry_hmac256_finalize (hmachd, &dlen);
620
_gcry_hmac256_release (hmachd);
623
if (dlen != sizeof (tv[tvidx].expect)
624
|| memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect)))
626
_gcry_hmac256_release (hmachd);
629
_gcry_hmac256_release (hmachd);
632
return 0; /* Succeeded. */
637
main (int argc, char **argv)
644
hmac256_context_t hd;
645
const unsigned char *digest;
651
assert (sizeof (u32) == 4);
653
setmode (fileno (stdin), O_BINARY);
658
pgm = strrchr (*argv, '/');
668
while (argc && last_argc != argc )
671
if (!strcmp (*argv, "--"))
676
else if (!strcmp (*argv, "--version"))
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 "
684
"There is NO WARRANTY, to the extent permitted by law.\n",
688
else if (!strcmp (*argv, "--binary"))
697
fprintf (stderr, "usage: %s [--binary] key [filename]\n", pgm);
703
setmode (fileno (stdout), O_BINARY);
708
keylen = strlen (key);
713
fprintf (stderr, "%s: fatal error: self-test failed\n", pgm);
717
for (; argc || use_stdin; argv++, argc--)
719
const char *fname = use_stdin? "-" : *argv;
720
fp = use_stdin? stdin : fopen (fname, "rb");
723
fprintf (stderr, "%s: can't open `%s': %s\n",
724
pgm, fname, strerror (errno));
727
hd = _gcry_hmac256_new (key, keylen);
730
fprintf (stderr, "%s: can't allocate context: %s\n",
731
pgm, strerror (errno));
734
while ( (n = fread (buffer, 1, sizeof buffer, fp)))
735
_gcry_hmac256_update (hd, buffer, n);
738
fprintf (stderr, "%s: error reading `%s': %s\n",
739
pgm, fname, strerror (errno));
745
digest = _gcry_hmac256_finalize (hd, &dlen);
748
fprintf (stderr, "%s: error computing HMAC: %s\n",
749
pgm, strerror (errno));
754
if (fwrite (digest, dlen, 1, stdout) != 1)
756
fprintf (stderr, "%s: error writing output: %s\n",
757
pgm, strerror (errno));
763
for (idx=0; idx < dlen; idx++)
764
printf ("%02x", digest[idx]);
765
_gcry_hmac256_release (hd);
771
printf (" %s\n", fname);
777
#endif /*STANDALONE*/
782
compile-command: "cc -Wall -g -I.. -DSTANDALONE -o hmac256 hmac256.c"