Example #1
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;
}
Example #2
0
int
fnmatch (const char *pattern, const char *string, int flags)
{
# if HANDLE_MULTIBYTE
  if (__builtin_expect (MB_CUR_MAX, 1) != 1)
    {
      mbstate_t ps;
      size_t n;
      const char *p;
      wchar_t *wpattern_malloc = NULL;
      wchar_t *wpattern;
      wchar_t *wstring_malloc = NULL;
      wchar_t *wstring;
      size_t alloca_used = 0;

      /* Convert the strings into wide characters.  */
      memset (&ps, '\0', sizeof (ps));
      p = pattern;
#ifdef _LIBC
      n = __strnlen (pattern, 1024);
#else
      n = strlen (pattern);
#endif
      if (__glibc_likely (n < 1024))
	{
	  wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
						 alloca_used);
	  n = mbsrtowcs (wpattern, &p, n + 1, &ps);
	  if (__glibc_unlikely (n == (size_t) -1))
	    /* Something wrong.
	       XXX Do we have to set `errno' to something which mbsrtows hasn't
	       already done?  */
	    return -1;
	  if (p)
	    {
	      memset (&ps, '\0', sizeof (ps));
	      goto prepare_wpattern;
	    }
	}
      else
	{
	prepare_wpattern:
	  n = mbsrtowcs (NULL, &pattern, 0, &ps);
	  if (__glibc_unlikely (n == (size_t) -1))
	    /* Something wrong.
	       XXX Do we have to set `errno' to something which mbsrtows hasn't
	       already done?  */
	    return -1;
	  if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
	    {
	      __set_errno (ENOMEM);
	      return -2;
	    }
	  wpattern_malloc = wpattern
	    = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
	  assert (mbsinit (&ps));
	  if (wpattern == NULL)
	    return -2;
	  (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
	}

      assert (mbsinit (&ps));
#ifdef _LIBC
      n = __strnlen (string, 1024);
#else
      n = strlen (string);
#endif
      p = string;
      if (__glibc_likely (n < 1024))
	{
	  wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
						alloca_used);
	  n = mbsrtowcs (wstring, &p, n + 1, &ps);
	  if (__glibc_unlikely (n == (size_t) -1))
	    {
	      /* Something wrong.
		 XXX Do we have to set `errno' to something which
		 mbsrtows hasn't already done?  */
	    free_return:
	      free (wpattern_malloc);
	      return -1;
	    }
	  if (p)
	    {
	      memset (&ps, '\0', sizeof (ps));
	      goto prepare_wstring;
	    }
	}
      else
	{
	prepare_wstring:
	  n = mbsrtowcs (NULL, &string, 0, &ps);
	  if (__glibc_unlikely (n == (size_t) -1))
	    /* Something wrong.
	       XXX Do we have to set `errno' to something which mbsrtows hasn't
	       already done?  */
	    goto free_return;
	  if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
	    {
	      free (wpattern_malloc);
	      __set_errno (ENOMEM);
	      return -2;
	    }

	  wstring_malloc = wstring
	    = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
	  if (wstring == NULL)
	    {
	      free (wpattern_malloc);
	      return -2;
	    }
	  assert (mbsinit (&ps));
	  (void) mbsrtowcs (wstring, &string, n + 1, &ps);
	}

      int res = internal_fnwmatch (wpattern, wstring, wstring + n,
				   flags & FNM_PERIOD, flags, NULL,
				   alloca_used);

      free (wstring_malloc);
      free (wpattern_malloc);

      return res;
    }
# endif  /* mbstate_t and mbsrtowcs or _LIBC.  */

  return internal_fnmatch (pattern, string, string + strlen (string),
			   flags & FNM_PERIOD, flags, NULL, 0);
}