aboutsummaryrefslogtreecommitdiff
path: root/cups/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'cups/hash.c')
-rw-r--r--cups/hash.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/cups/hash.c b/cups/hash.c
new file mode 100644
index 00000000..6b7b6dad
--- /dev/null
+++ b/cups/hash.c
@@ -0,0 +1,245 @@
+/*
+ * Hashing function for CUPS.
+ *
+ * Copyright 2015 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
+ * 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>
+#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, "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, "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 without CommonCrypto or GNU TLS...
+ */
+
+ 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);
+}