/*
 * Hashing function for CUPS.
 *
 * Copyright © 2015-2018 by Apple Inc.
 *
 * These coded instructions, statements, and computer programs are the
 * property of Apple Inc. and are protected by Federal copyright
 * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
 * which should have been included with this file.  If this file is
 * missing or damaged, see the license at "http://www.cups.org/".
 *
 * This file is subject to the Apple OS-Developed Software exception.
 */

/*
 * Include necessary headers...
 */

#include "cups-private.h"
#ifdef __APPLE__
#  include <CommonCrypto/CommonDigest.h>
#elif defined(HAVE_GNUTLS)
#  include <gnutls/crypto.h>
#else
#  include "md5-private.h"
#endif /* __APPLE__ */


/*
 * 'cupsHashData()' - Perform a hash function on the given data.
 *
 * The "algorithm" argument can be any of the registered, non-deprecated IPP
 * hash algorithms for the "job-password-encryption" attribute, including
 * "sha" for SHA-1, "sha-256" for SHA2-256, etc.
 *
 * The "hash" argument points to a buffer of "hashsize" bytes and should be at
 * least 64 bytes in length for all of the supported algorithms.
 *
 * The returned hash is binary data.
 *
 * @since CUPS 2.2/macOS 10.12@
 */

ssize_t					/* O - Size of hash or -1 on error */
cupsHashData(const char    *algorithm,	/* I - Algorithm name */
             const void    *data,	/* I - Data to hash */
             size_t        datalen,	/* I - Length of data to hash */
             unsigned char *hash,	/* I - Hash buffer */
             size_t        hashsize)	/* I - Size of hash buffer */
{
  if (!algorithm || !data || datalen == 0 || !hash || hashsize == 0)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad arguments to function"), 1);
    return (-1);
  }

#ifdef __APPLE__
  if (!strcmp(algorithm, "md5"))
  {
   /*
    * MD5 (deprecated but widely used...)
    */

    CC_MD5_CTX	ctx;			/* MD5 context */

    if (hashsize < CC_MD5_DIGEST_LENGTH)
      goto too_small;

    CC_MD5_Init(&ctx);
    CC_MD5_Update(&ctx, data, (CC_LONG)datalen);
    CC_MD5_Final(hash, &ctx);

    return (CC_MD5_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha"))
  {
   /*
    * SHA-1...
    */

    CC_SHA1_CTX	ctx;			/* SHA-1 context */

    if (hashsize < CC_SHA1_DIGEST_LENGTH)
      goto too_small;

    CC_SHA1_Init(&ctx);
    CC_SHA1_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA1_Final(hash, &ctx);

    return (CC_SHA1_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha2-224"))
  {
    CC_SHA256_CTX	ctx;		/* SHA-224 context */

    if (hashsize < CC_SHA224_DIGEST_LENGTH)
      goto too_small;

    CC_SHA224_Init(&ctx);
    CC_SHA224_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA224_Final(hash, &ctx);

    return (CC_SHA224_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha2-256"))
  {
    CC_SHA256_CTX	ctx;		/* SHA-256 context */

    if (hashsize < CC_SHA256_DIGEST_LENGTH)
      goto too_small;

    CC_SHA256_Init(&ctx);
    CC_SHA256_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA256_Final(hash, &ctx);

    return (CC_SHA256_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha2-384"))
  {
    CC_SHA512_CTX	ctx;		/* SHA-384 context */

    if (hashsize < CC_SHA384_DIGEST_LENGTH)
      goto too_small;

    CC_SHA384_Init(&ctx);
    CC_SHA384_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA384_Final(hash, &ctx);

    return (CC_SHA384_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha2-512"))
  {
    CC_SHA512_CTX	ctx;		/* SHA-512 context */

    if (hashsize < CC_SHA512_DIGEST_LENGTH)
      goto too_small;

    CC_SHA512_Init(&ctx);
    CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA512_Final(hash, &ctx);

    return (CC_SHA512_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha2-512_224"))
  {
    CC_SHA512_CTX	ctx;		/* SHA-512 context */
    unsigned char	temp[CC_SHA512_DIGEST_LENGTH];
                                        /* SHA-512 hash */

   /*
    * SHA2-512 truncated to 224 bits (28 bytes)...
    */

    if (hashsize < CC_SHA224_DIGEST_LENGTH)
      goto too_small;

    CC_SHA512_Init(&ctx);
    CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA512_Final(temp, &ctx);

    memcpy(hash, temp, CC_SHA224_DIGEST_LENGTH);

    return (CC_SHA224_DIGEST_LENGTH);
  }
  else if (!strcmp(algorithm, "sha2-512_256"))
  {
    CC_SHA512_CTX	ctx;		/* SHA-512 context */
    unsigned char	temp[CC_SHA512_DIGEST_LENGTH];
                                        /* SHA-512 hash */

   /*
    * SHA2-512 truncated to 256 bits (32 bytes)...
    */

    if (hashsize < CC_SHA256_DIGEST_LENGTH)
      goto too_small;

    CC_SHA512_Init(&ctx);
    CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
    CC_SHA512_Final(temp, &ctx);

    memcpy(hash, temp, CC_SHA256_DIGEST_LENGTH);

    return (CC_SHA256_DIGEST_LENGTH);
  }

#elif defined(HAVE_GNUTLS)
  gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN;
					/* Algorithm */
  unsigned char	temp[64];		/* Temporary hash buffer */
  size_t	tempsize = 0;		/* Truncate to this size? */

  if (!strcmp(algorithm, "md5"))
    alg = GNUTLS_DIG_MD5;
  else if (!strcmp(algorithm, "sha"))
    alg = GNUTLS_DIG_SHA1;
  else if (!strcmp(algorithm, "sha2-224"))
    alg = GNUTLS_DIG_SHA224;
  else if (!strcmp(algorithm, "sha2-256"))
    alg = GNUTLS_DIG_SHA256;
  else if (!strcmp(algorithm, "sha2-384"))
    alg = GNUTLS_DIG_SHA384;
  else if (!strcmp(algorithm, "sha2-512"))
    alg = GNUTLS_DIG_SHA512;
  else if (!strcmp(algorithm, "sha2-512_224"))
  {
    alg      = GNUTLS_DIG_SHA512;
    tempsize = 28;
  }
  else if (!strcmp(algorithm, "sha2-512_256"))
  {
    alg      = GNUTLS_DIG_SHA512;
    tempsize = 32;
  }

  if (alg != GNUTLS_DIG_UNKNOWN)
  {
    if (tempsize > 0)
    {
     /*
      * Truncate result to tempsize bytes...
      */

      if (hashsize < tempsize)
        goto too_small;

      gnutls_hash_fast(alg, data, datalen, temp);
      memcpy(hash, temp, tempsize);

      return ((ssize_t)tempsize);
    }

    if (hashsize < gnutls_hash_get_len(alg))
      goto too_small;

    gnutls_hash_fast(alg, data, datalen, hash);

    return (gnutls_hash_get_len(alg));
  }

#else
 /*
  * No hash support beyond MD5 without CommonCrypto or GNU TLS...
  */

  if (!strcmp(algorithm, "md5"))
  {
    _cups_md5_state_t	state;		/* MD5 state info */

    _cupsMD5Init(&state);
    _cupsMD5Append(&state, data, datalen);
    _cupsMD5Finish(&state, hash);

    return (16);
  }
  else if (hashsize < 64)
    goto too_small;
#endif /* __APPLE__ */

 /*
  * Unknown hash algorithm...
  */

  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown hash algorithm."), 1);

  return (-1);

 /*
  * We get here if the buffer is too small.
  */

  too_small:

  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1);
  return (-1);
}


/*
 * 'cupsHashString()' - Format a hash value as a hexadecimal string.
 *
 * The passed buffer must be at least 2 * hashsize + 1 characters in length.
 *
 * @since CUPS 2.2.7@
 */

const char *				/* O - Formatted string */
cupsHashString(
    const unsigned char *hash,		/* I - Hash */
    size_t              hashsize,	/* I - Size of hash */
    char                *buffer,	/* I - String buffer */
    size_t		bufsize)	/* I - Size of string buffer */
{
  char		*bufptr = buffer;	/* Pointer into buffer */
  static const char *hex = "0123456789abcdef";
					/* Hex characters (lowercase!) */


 /*
  * Range check input...
  */

  if (!hash || hashsize < 1 || !buffer || bufsize < (2 * hashsize + 1))
  {
    if (buffer)
      *buffer = '\0';
    return (NULL);
  }

 /*
  * Loop until we've converted the whole hash...
  */

  while (hashsize > 0)
  {
    *bufptr++ = hex[*hash >> 4];
    *bufptr++ = hex[*hash & 15];

    hash ++;
    hashsize --;
  }

  *bufptr = '\0';

  return (buffer);
}
