예제 #1
0
/* Finalize an operation and return the digest.  If R_DLEN is not NULL
   the length of the digest will be stored at that address.  The
   returned value is valid as long as the context exists.  On error
   NULL is returned. */
const void *
_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen)
{
  finalize (hd);
  if (hd->use_hmac)
    {
      hmac256_context_t tmphd;

      tmphd = _gcry_hmac256_new (NULL, 0);
      if (!tmphd)
	return NULL;

      _gcry_hmac256_update (tmphd, hd->opad, 64);
      _gcry_hmac256_update (tmphd, hd->buf, 32);
      finalize (tmphd);
      memcpy (hd->buf, tmphd->buf, 32);
      _gcry_hmac256_release (tmphd);
    }
  if (r_dlen)
    *r_dlen = 32;
  return (void*)hd->buf;
}
예제 #2
0
int
main (int argc, char **argv)
{
  const char *pgm;
  int last_argc = -1;
  const char *key;
  size_t keylen;
  FILE *fp;
  hmac256_context_t hd;
  const unsigned char *digest;
  char buffer[4096];
  size_t n, dlen, idx;
  int use_stdin = 0;
  int use_binary = 0;

  assert (sizeof (u32) == 4);
#ifdef __WIN32
  setmode (fileno (stdin), O_BINARY);
#endif

  if (argc)
    {
      pgm = strrchr (*argv, '/');
      if (pgm)
        pgm++;
      else
        pgm = *argv;
      argc--; argv++;
    }
  else
    pgm = "?";

  while (argc && last_argc != argc )
    {
      last_argc = argc;
      if (!strcmp (*argv, "--"))
        {
          argc--; argv++;
          break;
        }
      else if (!strcmp (*argv, "--version"))
        {
          fputs ("hmac256 (Libgcrypt) " VERSION "\n"
                 "Copyright (C) 2008 Free Software Foundation, Inc.\n"
                 "License LGPLv2.1+: GNU LGPL version 2.1 or later "
                 "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
                 "This is free software: you are free to change and "
                 "redistribute it.\n"
                 "There is NO WARRANTY, to the extent permitted by law.\n",
                 stdout);
          exit (0);
        }
      else if (!strcmp (*argv, "--binary"))
        {
          argc--; argv++;
          use_binary = 1;
        }
    }

  if (argc < 1)
    {
      fprintf (stderr, "usage: %s [--binary] key [filename]\n", pgm);
      exit (1);
    }

#ifdef __WIN32
  if (use_binary)
    setmode (fileno (stdout), O_BINARY);
#endif

  key = *argv;
  argc--, argv++;
  keylen = strlen (key);
  use_stdin = !argc;

  if (selftest ())
    {
      fprintf (stderr, "%s: fatal error: self-test failed\n", pgm);
      exit (2);
    }

  for (; argc || use_stdin; argv++, argc--)
    {
      const char *fname = use_stdin? "-" : *argv;
      fp = use_stdin? stdin : fopen (fname, "rb");
      if (!fp)
        {
          fprintf (stderr, "%s: can't open `%s': %s\n",
                   pgm, fname, strerror (errno));
          exit (1);
        }
      hd = _gcry_hmac256_new (key, keylen);
      if (!hd)
        {
          fprintf (stderr, "%s: can't allocate context: %s\n",
                   pgm, strerror (errno));
          exit (1);
        }
      while ( (n = fread (buffer, 1, sizeof buffer, fp)))
        _gcry_hmac256_update (hd, buffer, n);
      if (ferror (fp))
        {
          fprintf (stderr, "%s: error reading `%s': %s\n",
                   pgm, fname, strerror (errno));
          exit (1);
        }
      if (!use_stdin)
        fclose (fp);

      digest = _gcry_hmac256_finalize (hd, &dlen);
      if (!digest)
        {
          fprintf (stderr, "%s: error computing HMAC: %s\n",
                   pgm, strerror (errno));
          exit (1);
        }
      if (use_binary)
        {
          if (fwrite (digest, dlen, 1, stdout) != 1)
            {
              fprintf (stderr, "%s: error writing output: %s\n",
                       pgm, strerror (errno));
              exit (1);
            }
          if (use_stdin)
            break;
        }
      else
        {
          for (idx=0; idx < dlen; idx++)
            printf ("%02x", digest[idx]);
          _gcry_hmac256_release (hd);
          if (use_stdin)
            {
              putchar ('\n');
              break;
            }
          printf ("  %s\n", fname);
        }
    }

  return 0;
}
예제 #3
0
static int
selftest (void)
{
  static struct
  {
    const char * const desc;
    const char * const data;
    const char * const key;
    const unsigned char expect[32];
  } tv[] =
    {
      { "data-28 key-4",
        "what do ya want for nothing?",
        "Jefe",
	{ 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
          0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
          0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
          0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } },

      { "data-9 key-20",
        "Hi There",
	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
        "\x0b\x0b\x0b\x0b",
        { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
          0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
          0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
          0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } },

      { "data-50 key-20",
        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
        "\xdd\xdd",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa",
        { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
          0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
          0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
          0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } },

      { "data-50 key-26",
        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
        "\xcd\xcd",
	"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
	{ 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
          0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
          0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
          0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } },

      { "data-54 key-131",
        "Test Using Larger Than Block-Size Key - Hash Key First",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa",
	{ 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
          0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
          0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
          0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } },

      { "data-152 key-131",
        "This is a test using a larger than block-size key and a larger "
        "than block-size data. The key needs to be hashed before being "
        "used by the HMAC algorithm.",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
        "\xaa\xaa\xaa",
	{ 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
          0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
          0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
          0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } },

      { NULL }
    };
  int tvidx;

  for (tvidx=0; tv[tvidx].desc; tvidx++)
    {
      hmac256_context_t hmachd;
      const unsigned char *digest;
      size_t dlen;

      hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
      if (!hmachd)
        return -1;
      _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
      digest = _gcry_hmac256_finalize (hmachd, &dlen);
      if (!digest)
        {
          _gcry_hmac256_release (hmachd);
          return -1;
        }
      if (dlen != sizeof (tv[tvidx].expect)
          || memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect)))
        {
          _gcry_hmac256_release (hmachd);
          return -1;
        }
      _gcry_hmac256_release (hmachd);
    }

  return 0; /* Succeeded. */
}
예제 #4
0
/* Convenience function to compute the HMAC-SHA256 of one file.  The
   user needs to provide a buffer RESULT of at least 32 bytes, he
   needs to put the size of the buffer into RESULTSIZE and the
   FILENAME.  KEY and KEYLEN are as described for _gcry_hmac256_new.
   On success the function returns the valid length of the result
   buffer (which will be 32) or -1 on error.  On error ERRNO is set
   appropriate.  */
int
_gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
                    const void *key, size_t keylen)
{
  FILE *fp;
  hmac256_context_t hd;
  size_t buffer_size, nread, digestlen;
  char *buffer;
  const unsigned char *digest;

  fp = fopen (filename, "rb");
  if (!fp)
    return -1;

  hd = _gcry_hmac256_new (key, keylen);
  if (!hd)
    {
      fclose (fp);
      return -1;
    }

  buffer_size = 32768;
  buffer = malloc (buffer_size);
  if (!buffer)
    {
      fclose (fp);
      _gcry_hmac256_release (hd);
      return -1;
    }

  while ( (nread = fread (buffer, 1, buffer_size, fp)))
    _gcry_hmac256_update (hd, buffer, nread);

  free (buffer);

  if (ferror (fp))
    {
      fclose (fp);
      _gcry_hmac256_release (hd);
      return -1;
    }

  fclose (fp);

  digest = _gcry_hmac256_finalize (hd, &digestlen);
  if (!digest)
    {
      _gcry_hmac256_release (hd);
      return -1;
    }

  if (digestlen > resultsize)
    {
      _gcry_hmac256_release (hd);
      gpg_err_set_errno (EINVAL);
      return -1;
    }
  memcpy (result, digest, digestlen);
  _gcry_hmac256_release (hd);

  return digestlen;
}
예제 #5
0
/* Create a new context.  On error NULL is returned and errno is set
   appropriately.  If KEY is given the function computes HMAC using
   this key; with KEY given as NULL, a plain SHA-256 digest is
   computed.  */
hmac256_context_t
_gcry_hmac256_new (const void *key, size_t keylen)
{
  hmac256_context_t hd;

  hd = malloc (sizeof *hd);
  if (!hd)
    return NULL;

  hd->h0 = 0x6a09e667;
  hd->h1 = 0xbb67ae85;
  hd->h2 = 0x3c6ef372;
  hd->h3 = 0xa54ff53a;
  hd->h4 = 0x510e527f;
  hd->h5 = 0x9b05688c;
  hd->h6 = 0x1f83d9ab;
  hd->h7 = 0x5be0cd19;
  hd->nblocks = 0;
  hd->count = 0;
  hd->finalized = 0;
  hd->use_hmac = 0;

  if (key)
    {
      int i;
      unsigned char ipad[64];

      memset (ipad, 0, 64);
      memset (hd->opad, 0, 64);
      if (keylen <= 64)
        {
          memcpy (ipad, key, keylen);
          memcpy (hd->opad, key, keylen);
        }
      else
        {
          hmac256_context_t tmphd;

          tmphd = _gcry_hmac256_new (NULL, 0);
          if (!tmphd)
            {
              free (hd);
              return NULL;
            }
          _gcry_hmac256_update (tmphd, key, keylen);
          finalize (tmphd);
          memcpy (ipad, tmphd->buf, 32);
          memcpy (hd->opad, tmphd->buf, 32);
          _gcry_hmac256_release (tmphd);
        }
      for (i=0; i < 64; i++)
        {
          ipad[i] ^= 0x36;
          hd->opad[i] ^= 0x5c;
        }
      hd->use_hmac = 1;
      _gcry_hmac256_update (hd, ipad, 64);
      my_wipememory (ipad, 64);
    }

  return hd;
}