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
void *
sha384_buffer (const char *buffer, size_t len, void *resblock)
{
    struct sha512_ctx ctx;

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

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

    /* Put result in desired memory area.  */
    return sha384_finish_ctx (&ctx, resblock);
}
Exemplo n.º 3
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.º 4
0
/* FIXME: Avoid code duplication */
int
sha384_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.  */
    sha384_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.  */
    sha384_finish_ctx (&ctx, resblock);
    free (buffer);
    return 0;
}