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