Exemplo n.º 1
0
int
hmac_sha512 (const void *key, size_t keylen,
             const void *in, size_t inlen, void *resbuf)
{
  struct sha512_ctx inner;
  struct sha512_ctx outer;
  char optkeybuf[64];
  char block[128];
  char innerhash[64];

  /* Reduce the key's size, so that it becomes <= 128 bytes large.  */

  if (keylen > 128)
    {
      struct sha512_ctx keyhash;

      sha512_init_ctx (&keyhash);
      sha512_process_bytes (key, keylen, &keyhash);
      sha512_finish_ctx (&keyhash, optkeybuf);

      key = optkeybuf;
      keylen = 128;
    }

  /* Compute INNERHASH from KEY and IN.  */

  sha512_init_ctx (&inner);

  memset (block, IPAD, sizeof (block));
  memxor (block, key, keylen);

  sha512_process_block (block, 128, &inner);
  sha512_process_bytes (in, inlen, &inner);

  sha512_finish_ctx (&inner, innerhash);

  /* Compute result from KEY and INNERHASH.  */

  sha512_init_ctx (&outer);

  memset (block, OPAD, sizeof (block));
  memxor (block, key, keylen);

  sha512_process_block (block, 128, &outer);
  sha512_process_bytes (innerhash, 64, &outer);

  sha512_finish_ctx (&outer, resbuf);

  return 0;
}
Exemplo n.º 2
0
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER.  The
   result is always in little endian byte order, so that a byte-wise
   output yields to the wanted ASCII representation of the message
   digest.  */
void *
sha512_buffer (const char *buffer, size_t len, void *resblock)
{
    struct sha512_ctx ctx;

    /* Initialize the computation context.  */
    sha512_init_ctx (&ctx);

    /* Process whole buffer but last len % 128 bytes.  */
    sha512_process_bytes (buffer, len, &ctx);

    /* Put result in desired memory area.  */
    return sha512_finish_ctx (&ctx, resblock);
}
Exemplo n.º 3
0
/*
 * Calls multiple times sha512_file(), sha512_file_ctx(), sha512_buffer() with
 * random offset & count parameters. Checks that all hash functions return identical
 * hash values.
 */
static void test_sha512_file_cross_memory()
{
	const size_t file_size = 2 * 32768; // 2 * BLOCKSIZE
	int fd = create_file(file_size);
	BOOST_CHECK_MESSAGE(fd >= 0, "could not create temporary file");

	const size_t num_iter = 1000;
	char hash_file[64], hash_file_ctx[64], hash_memory[64];
	struct sha512_ctx ctx;
	std::unique_ptr<char[]> buffer(new char[file_size]);
	int err;

	for (size_t i = 0; i < num_iter; ++i) {
		const off_t offset = rand() % file_size;
		const size_t count = rand() % file_size;

		sha512_init_ctx(&ctx);
		err = sha512_file_ctx(fd, offset, count, &ctx);
		if (offset + count > file_size) {
			BOOST_CHECK_MESSAGE(err == -ESPIPE,
				"sha512_file_ctx() must return ESPIPE when offset + count > file_size");
		} else {
			BOOST_CHECK_MESSAGE(err == 0,
				"Unexpected error during sha512_file_ctx() call");
		}
		sha512_finish_ctx(&ctx, hash_file_ctx);

		err = sha512_file(fd, offset, count, hash_file);
		if (offset + count > file_size) {
			BOOST_CHECK_MESSAGE(err == -ESPIPE,
				"sha512_file() must return ESPIPE when offset + count > file_size");
			continue;
		} else {
			BOOST_CHECK_MESSAGE(err == 0,
				"Unexpected error during sha512_file() call");
		}

		err = pread(fd, buffer.get(), count, offset);
		BOOST_CHECK_MESSAGE(err == static_cast<int>(count), "pread() failed, could not read test file");
		sha512_buffer(buffer.get(), count, hash_memory);

		BOOST_CHECK_MESSAGE(memcmp(hash_file, hash_memory, sizeof(hash_file)) == 0,
			"hash_file != hash_memory: sha512_file() or sha512_buffer() function is broken");
		BOOST_CHECK_MESSAGE(memcmp(hash_file_ctx, hash_memory, sizeof(hash_file)) == 0,
			"hash_file_ctx != hash_memory: sha512_file_ctx() function is broken");
	}
}
Exemplo n.º 4
0
char *
__sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
{
  unsigned char alt_result[64]
    __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
  unsigned char temp_result[64]
    __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
  size_t salt_len;
  size_t key_len;
  size_t cnt;
  char *cp;
  char *copied_key = NULL;
  char *copied_salt = NULL;
  char *p_bytes;
  char *s_bytes;
  /* Default number of rounds.  */
  size_t rounds = ROUNDS_DEFAULT;
  bool rounds_custom = false;
  size_t alloca_used = 0;
  char *free_key = NULL;
  char *free_pbytes = NULL;

  /* Find beginning of salt string.  The prefix should normally always
     be present.  Just in case it is not.  */
  if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
    /* Skip salt prefix.  */
    salt += sizeof (sha512_salt_prefix) - 1;

  if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
      == 0)
    {
      const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
      char *endp;
      unsigned long int srounds = strtoul (num, &endp, 10);
      if (*endp == '$')
	{
	  salt = endp + 1;
	  rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
	  rounds_custom = true;
	}
    }

  salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
  key_len = strlen (key);

  if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
    {
      char *tmp;

      if (__libc_use_alloca (alloca_used + key_len + __alignof__ (uint64_t)))
	tmp = alloca_account (key_len + __alignof__ (uint64_t), alloca_used);
      else
	{
	  free_key = tmp = (char *) malloc (key_len + __alignof__ (uint64_t));
	  if (tmp == NULL)
	    return NULL;
	}

      key = copied_key =
	memcpy (tmp + __alignof__ (uint64_t)
		- (tmp - (char *) 0) % __alignof__ (uint64_t),
		key, key_len);
      assert ((key - (char *) 0) % __alignof__ (uint64_t) == 0);
    }

  if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
    {
      char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
      salt = copied_salt =
	memcpy (tmp + __alignof__ (uint64_t)
		- (tmp - (char *) 0) % __alignof__ (uint64_t),
		salt, salt_len);
      assert ((salt - (char *) 0) % __alignof__ (uint64_t) == 0);
    }

#ifdef USE_NSS
  /* Initialize libfreebl3.  */
  NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
  if (nss_ictx == NULL)
    {
      free (free_key);
      return NULL;
    }
  NSSLOWHASHContext *nss_ctx = NULL;
  NSSLOWHASHContext *nss_alt_ctx = NULL;
#else
  struct sha512_ctx ctx;
  struct sha512_ctx alt_ctx;
#endif

  /* Prepare for the real work.  */
  sha512_init_ctx (&ctx, nss_ctx);

  /* Add the key string.  */
  sha512_process_bytes (key, key_len, &ctx, nss_ctx);

  /* The last part is the salt string.  This must be at most 16
     characters and it ends at the first `$' character.  */
  sha512_process_bytes (salt, salt_len, &ctx, nss_ctx);


  /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.  The
     final result will be added to the first context.  */
  sha512_init_ctx (&alt_ctx, nss_alt_ctx);

  /* Add key.  */
  sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);

  /* Add salt.  */
  sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);

  /* Add key again.  */
  sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);

  /* Now get result of this (64 bytes) and add it to the other
     context.  */
  sha512_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);

  /* Add for any character in the key one byte of the alternate sum.  */
  for (cnt = key_len; cnt > 64; cnt -= 64)
    sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
  sha512_process_bytes (alt_result, cnt, &ctx, nss_ctx);

  /* Take the binary representation of the length of the key and for every
     1 add the alternate sum, for every 0 the key.  */
  for (cnt = key_len; cnt > 0; cnt >>= 1)
    if ((cnt & 1) != 0)
      sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
    else
      sha512_process_bytes (key, key_len, &ctx, nss_ctx);

  /* Create intermediate result.  */
  sha512_finish_ctx (&ctx, nss_ctx, alt_result);

  /* Start computation of P byte sequence.  */
  sha512_init_ctx (&alt_ctx, nss_alt_ctx);

  /* For every character in the password add the entire password.  */
  for (cnt = 0; cnt < key_len; ++cnt)
    sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);

  /* Finish the digest.  */
  sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);

  /* Create byte sequence P.  */
  if (__libc_use_alloca (alloca_used + key_len))
    cp = p_bytes = (char *) alloca (key_len);
  else
    {
      free_pbytes = cp = p_bytes = (char *)malloc (key_len);
      if (free_pbytes == NULL)
	{
	  free (free_key);
	  return NULL;
	}
    }

  for (cnt = key_len; cnt >= 64; cnt -= 64)
    cp = mempcpy (cp, temp_result, 64);
  memcpy (cp, temp_result, cnt);

  /* Start computation of S byte sequence.  */
  sha512_init_ctx (&alt_ctx, nss_alt_ctx);

  /* For every character in the password add the entire password.  */
  for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
    sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);

  /* Finish the digest.  */
  sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);

  /* Create byte sequence S.  */
  cp = s_bytes = alloca (salt_len);
  for (cnt = salt_len; cnt >= 64; cnt -= 64)
    cp = mempcpy (cp, temp_result, 64);
  memcpy (cp, temp_result, cnt);

  /* Repeatedly run the collected hash value through SHA512 to burn
     CPU cycles.  */
  for (cnt = 0; cnt < rounds; ++cnt)
    {
      /* New context.  */
      sha512_init_ctx (&ctx, nss_ctx);

      /* Add key or last result.  */
      if ((cnt & 1) != 0)
	sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
      else
	sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);

      /* Add salt for numbers not divisible by 3.  */
      if (cnt % 3 != 0)
	sha512_process_bytes (s_bytes, salt_len, &ctx, nss_ctx);

      /* Add key for numbers not divisible by 7.  */
      if (cnt % 7 != 0)
	sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);

      /* Add key or last result.  */
      if ((cnt & 1) != 0)
	sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
      else
	sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);

      /* Create intermediate result.  */
      sha512_finish_ctx (&ctx, nss_ctx, alt_result);
    }

#ifdef USE_NSS
  /* Free libfreebl3 resources. */
  NSSLOW_Shutdown (nss_ictx);
#endif

  /* Now we can construct the result string.  It consists of three
     parts.  */
  cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
  buflen -= sizeof (sha512_salt_prefix) - 1;

  if (rounds_custom)
    {
      int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
			sha512_rounds_prefix, rounds);
      cp += n;
      buflen -= n;
    }

  cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
  buflen -= MIN ((size_t) MAX (0, buflen), salt_len);

  if (buflen > 0)
    {
      *cp++ = '$';
      --buflen;
    }

  __b64_from_24bit (&cp, &buflen,
		    alt_result[0], alt_result[21], alt_result[42], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[22], alt_result[43], alt_result[1], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[44], alt_result[2], alt_result[23], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[3], alt_result[24], alt_result[45], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[25], alt_result[46], alt_result[4], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[47], alt_result[5], alt_result[26], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[6], alt_result[27], alt_result[48], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[28], alt_result[49], alt_result[7], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[50], alt_result[8], alt_result[29], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[9], alt_result[30], alt_result[51], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[31], alt_result[52], alt_result[10], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[53], alt_result[11], alt_result[32], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[12], alt_result[33], alt_result[54], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[34], alt_result[55], alt_result[13], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[56], alt_result[14], alt_result[35], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[15], alt_result[36], alt_result[57], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[37], alt_result[58], alt_result[16], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[59], alt_result[17], alt_result[38], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[18], alt_result[39], alt_result[60], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[40], alt_result[61], alt_result[19], 4);
  __b64_from_24bit (&cp, &buflen,
		    alt_result[62], alt_result[20], alt_result[41], 4);
  __b64_from_24bit (&cp, &buflen,
		    0, 0, alt_result[63], 2);

  if (buflen <= 0)
    {
      __set_errno (ERANGE);
      buffer = NULL;
    }
  else
    *cp = '\0';		/* Terminate the string.  */

  /* Clear the buffer for the intermediate result so that people
     attaching to processes or reading core dumps cannot get any
     information.  We do it in this way to clear correct_words[]
     inside the SHA512 implementation as well.  */
#ifndef USE_NSS
  __sha512_init_ctx (&ctx);
  __sha512_finish_ctx (&ctx, alt_result);
  memset (&ctx, '\0', sizeof (ctx));
  memset (&alt_ctx, '\0', sizeof (alt_ctx));
#endif
  memset (temp_result, '\0', sizeof (temp_result));
  memset (p_bytes, '\0', key_len);
  memset (s_bytes, '\0', salt_len);
  if (copied_key != NULL)
    memset (copied_key, '\0', key_len);
  if (copied_salt != NULL)
    memset (copied_salt, '\0', salt_len);

  free (free_key);
  free (free_pbytes);
  return buffer;
}
Exemplo n.º 5
0
/* Compute SHA512 message digest for bytes read from STREAM.  The
   resulting message digest number will be written into the 64 bytes
   beginning at RESBLOCK.  */
int
sha512_stream (FILE *stream, void *resblock)
{
    struct sha512_ctx ctx;
    size_t sum;

    char *buffer = (char *)malloc (BLOCKSIZE + 72);
    if (!buffer)
        return 1;

    /* Initialize the computation context.  */
    sha512_init_ctx (&ctx);

    /* Iterate over full file contents.  */
    while (1)
    {
        /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
           computation function processes the whole buffer so that with the
           next round of the loop another block can be read.  */
        size_t n;
        sum = 0;

        /* Read block.  Take care for partial reads.  */
        while (1)
        {
            n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);

            sum += n;

            if (sum == BLOCKSIZE)
                break;

            if (n == 0)
            {
                /* Check for the error flag IFF N == 0, so that we don't
                   exit the loop after a partial read due to e.g., EAGAIN
                   or EWOULDBLOCK.  */
                if (ferror (stream))
                {
                    free (buffer);
                    return 1;
                }
                goto process_partial_block;
            }

            /* We've read at least one byte, so ignore errors.  But always
               check for EOF, since feof may be true even though N > 0.
               Otherwise, we could end up calling fread after EOF.  */
            if (feof (stream))
                goto process_partial_block;
        }

        /* Process buffer with BLOCKSIZE bytes.  Note that
                          BLOCKSIZE % 128 == 0
         */
        sha512_process_block (buffer, BLOCKSIZE, &ctx);
    }

process_partial_block:
    ;

    /* Process any remaining bytes.  */
    if (sum > 0)
        sha512_process_bytes (buffer, sum, &ctx);

    /* Construct result in desired memory.  */
    sha512_finish_ctx (&ctx, resblock);
    free (buffer);
    return 0;
}