]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/hash.c
Merge pull request #5621 from zdohnal/cgigetarray-sigsegv
[thirdparty/cups.git] / cups / hash.c
index ede546167b202bdde7f74ed56ccdf8b7db5ab7c0..4fbb443db10cbf2180bb2af6266ed00a177d9a89 100644 (file)
@@ -1,15 +1,10 @@
 /*
  * Hashing function for CUPS.
  *
- * Copyright 2015-2016 by Apple Inc.
+ * Copyright © 2015-2019 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.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
@@ -21,6 +16,9 @@
 #  include <CommonCrypto/CommonDigest.h>
 #elif defined(HAVE_GNUTLS)
 #  include <gnutls/crypto.h>
+#  include "md5-internal.h"
+#else
+#  include "md5-internal.h"
 #endif /* __APPLE__ */
 
 
@@ -53,7 +51,24 @@ cupsHashData(const char    *algorithm,       /* I - Algorithm name */
   }
 
 #ifdef __APPLE__
-  if (!strcmp(algorithm, "sha"))
+  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...
@@ -171,7 +186,25 @@ cupsHashData(const char    *algorithm,     /* I - Algorithm name */
   unsigned char        temp[64];               /* Temporary hash buffer */
   size_t       tempsize = 0;           /* Truncate to this size? */
 
-  if (!strcmp(algorithm, "sha"))
+
+  if (!strcmp(algorithm, "md5"))
+  {
+   /*
+    * Some versions of GNU TLS disable MD5 without warning...
+    */
+
+    _cups_md5_state_t  state;          /* MD5 state info */
+
+    if (hashsize < 16)
+      goto too_small;
+
+    _cupsMD5Init(&state);
+    _cupsMD5Append(&state, data, datalen);
+    _cupsMD5Finish(&state, hash);
+
+    return (16);
+  }
+  else if (!strcmp(algorithm, "sha"))
     alg = GNUTLS_DIG_SHA1;
   else if (!strcmp(algorithm, "sha2-224"))
     alg = GNUTLS_DIG_SHA224;
@@ -214,15 +247,28 @@ cupsHashData(const char    *algorithm,    /* I - Algorithm name */
 
     gnutls_hash_fast(alg, data, datalen, hash);
 
-    return (gnutls_hash_get_len(alg));
+    return ((ssize_t)gnutls_hash_get_len(alg));
   }
 
 #else
  /*
-  * No hash support without CommonCrypto or GNU TLS...
+  * No hash support beyond MD5 without CommonCrypto or GNU TLS...
   */
 
-  if (hashsize < 64)
+  if (!strcmp(algorithm, "md5"))
+  {
+    _cups_md5_state_t  state;          /* MD5 state info */
+
+    if (hashsize < 16)
+      goto too_small;
+
+    _cupsMD5Init(&state);
+    _cupsMD5Append(&state, data, datalen);
+    _cupsMD5Finish(&state, hash);
+
+    return (16);
+  }
+  else if (hashsize < 64)
     goto too_small;
 #endif /* __APPLE__ */
 
@@ -243,3 +289,53 @@ cupsHashData(const char    *algorithm,     /* I - Algorithm name */
   _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);
+}