Import Debian changes 4.89-2+deb9u4
[hcoop/debian/exim4.git] / src / hash.c
similarity index 88%
rename from src/auths/sha1.c
rename to src/hash.c
index 67a1191..7590d55 100644 (file)
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) University of Cambridge 1995 - 2009 */
-/* See the file NOTICE for conditions of use and distribution. */
+/*
+ *  Exim - an Internet mail transport agent
+ *
+ *  Copyright (C) 2016  Exim maintainers
+ *  Copyright (c) University of Cambridge 1995 - 2016
+ *
+ *  Hash interface functions
+ */
 
 #ifndef STAND_ALONE
-#include "../exim.h"
+# include "exim.h"
+
+#else
 
 /* For stand-alone testing, we need to have the structure defined, and
 to be able to do I/O */
 
-#else
-#include <stdio.h>
-#include <stdlib.h>
+# include <stdio.h>
+# include <stdlib.h>
 typedef unsigned char uschar;
 typedef struct sha1 {
   unsigned int H[5];
   unsigned int length;
   }
 sha1;
+#endif /*STAND_ALONE*/
+
+#include <assert.h>
+
+/******************************************************************************/
+#ifdef SHA_OPENSSL
+
+BOOL
+exim_sha_init(hctx * h, hashmethod m)
+{
+switch (h->method = m)
+  {
+  case HASH_SHA1:   h->hashlen = 20; SHA1_Init  (&h->u.sha1); break;
+  case HASH_SHA256: h->hashlen = 32; SHA256_Init(&h->u.sha2); break;
+  default:         h->hashlen = 0; return FALSE;
+  }
+return TRUE;
+}
+
+
+void
+exim_sha_update(hctx * h, const uschar * data, int len)
+{
+switch (h->method)
+  {
+  case HASH_SHA1:   SHA1_Update  (&h->u.sha1, data, len); break;
+  case HASH_SHA256: SHA256_Update(&h->u.sha2, data, len); break;
+  /* should be blocked by init not handling these, but be explicit to
+   * guard against accidents later (and hush up clang -Wswitch) */
+  default: assert(0);
+  }
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+switch (h->method)
+  {
+  case HASH_SHA1:   SHA1_Final  (b->data, &h->u.sha1); break;
+  case HASH_SHA256: SHA256_Final(b->data, &h->u.sha2); break;
+  default: assert(0);
+  }
+}
+
+
+
+#elif defined(SHA_GNUTLS)
+/******************************************************************************/
+
+BOOL
+exim_sha_init(hctx * h, hashmethod m)
+{
+switch (h->method = m)
+  {
+  case HASH_SHA1:     h->hashlen = 20; gnutls_hash_init(&h->sha, GNUTLS_DIG_SHA1); break;
+  case HASH_SHA256:   h->hashlen = 32; gnutls_hash_init(&h->sha, GNUTLS_DIG_SHA256); break;
+#ifdef EXIM_HAVE_SHA3
+  case HASH_SHA3_256: h->hashlen = 32; gnutls_hash_init(&h->sha, GNUTLS_DIG_SHA3_256); break;
 #endif
+  default: h->hashlen = 0; return FALSE;
+  }
+return TRUE;
+}
 
 
+void
+exim_sha_update(hctx * h, const uschar * data, int len)
+{
+gnutls_hash(h->sha, data, len);
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+gnutls_hash_output(h->sha, b->data);
+}
+
+
+
+#elif defined(SHA_GCRYPT)
+/******************************************************************************/
+
+BOOL
+exim_sha_init(hctx * h, hashmethod m)
+{
+switch (h->method = m)
+  {
+  case HASH_SHA1:   h->hashlen = 20; gcry_md_open(&h->sha, GCRY_MD_SHA1, 0); break;
+  case HASH_SHA256: h->hashlen = 32; gcry_md_open(&h->sha, GCRY_MD_SHA256, 0); break;
+  default:         h->hashlen = 0; return FALSE;
+  }
+return TRUE;
+}
+
+
+void
+exim_sha_update(hctx * h, const uschar * data, int len)
+{
+gcry_md_write(h->sha, data, len);
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+memcpy(b->data, gcry_md_read(h->sha, 0), h->hashlen);
+}
+
+
+
+
+#elif defined(SHA_POLARSSL)
+/******************************************************************************/
+
+BOOL
+exim_sha_init(hctx * h, hashmethod m)
+{
+switch (h->method = m)
+  {
+  case HASH_SHA1:   h->hashlen = 20; sha1_starts(&h->u.sha1);    break;
+  case HASH_SHA256: h->hashlen = 32; sha2_starts(&h->u.sha2, 0); break;
+  default:         h->hashlen = 0; return FALSE;
+  }
+return TRUE;
+}
+
+
+void
+exim_sha_update(hctx * h, const uschar * data, int len)
+{
+switch (h->method)
+  {
+  case HASH_SHA1:   sha1_update(h->u.sha1, US data, len); break;
+  case HASH_SHA256: sha2_update(h->u.sha2, US data, len); break;
+  }
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+switch (h->method)
+  {
+  case HASH_SHA1:   sha1_finish(h->u.sha1, b->data); break;
+  case HASH_SHA256: sha2_finish(h->u.sha2, b->data); break;
+  }
+}
+
+
+
+
+#elif defined(SHA_NATIVE)
+/******************************************************************************/
+/* Only sha-1 supported */
 
 /*************************************************
 *        Start off a new SHA-1 computation.      *
@@ -33,8 +193,8 @@ Argument:  pointer to sha1 storage structure
 Returns:   nothing
 */
 
-void
-sha1_start(sha1 *base)
+static void
+native_sha1_start(sha1 *base)
 {
 base->H[0] = 0x67452301;
 base->H[1] = 0xefcdab89;
@@ -59,18 +219,18 @@ Arguments:
 Returns:     nothing
 */
 
-void
-sha1_mid(sha1 *base, const uschar *text)
+static void
+native_sha1_mid(sha1 *base, const uschar *text)
 {
-register int i;
-unsigned int A, B, C, D, E;
-unsigned int W[80];
+int i;
+uint A, B, C, D, E;
+uint W[80];
 
 base->length += 64;
 
 for (i = 0; i < 16; i++)
   {
-  W[i] = (text[0] << 24) | (text[1] << 16) | (text[2] << 8) | text[3];
+  W[i] = ((uint)text[0] << 24) | (text[1] << 16) | (text[2] << 8) | text[3];
   text += 4;
   }
 
@@ -158,8 +318,8 @@ Arguments:
 Returns:    nothing
 */
 
-void
-sha1_end(sha1 *base, const uschar *text, int length, uschar *digest)
+static void
+native_sha1_end(sha1 *base, const uschar *text, int length, uschar *digest)
 {
 int i;
 uschar work[64];
@@ -168,7 +328,7 @@ uschar work[64];
 
 while (length >= 64)
   {
-  sha1_mid(base, text);
+  native_sha1_mid(base, text);
   text += 64;
   length -= 64;
   }
@@ -184,7 +344,7 @@ work[length] = 0x80;
 if (length > 55)
   {
   memset(work+length+1, 0, 63-length);
-  sha1_mid(base, work);
+  native_sha1_mid(base, work);
   base->length -= 64;
   memset(work, 0, 56);
   }
@@ -210,7 +370,7 @@ memset(work+56, 0, 4);
 
 /* Process the final 64-byte chunk */
 
-sha1_mid(base, work);
+native_sha1_mid(base, work);
 
 /* Pass back the result, high-order byte first in each word. */
 
@@ -226,13 +386,113 @@ for (i = 0; i < 5; i++)
 
 
 
+
+
+
+# ifdef notdef
+BOOL
+exim_sha_init(hctx * h, hashmethod m)
+{
+h->hashlen = 20;
+native_sha1_start(&h->sha1);
+return TRUE;
+}
+
+
+void
+exim_sha_update(hctx * h, const uschar * data, int len)
+{
+native_sha1_mid(&h->sha1, US data);    /* implicit size always 64 */
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+
+native_sha1_end(&h->sha1, NULL, 0, b->data);
+}
+# endif
+
+
+#endif
+/******************************************************************************/
+
+/* Common to all library versions */
+int
+exim_sha_hashlen(hctx * h)
+{
+return h->method == HASH_SHA1 ? 20
+     : h->method == HASH_SHA256 ? 32
+     : 0;
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+/* Original sha-1 interface used by crypteq{shal1},
+${sha1:} ${hmac:} and ${prvs:} */
+
+#ifdef SHA_NATIVE
+
+void
+sha1_start(hctx * h)
+{
+native_sha1_start(&h->sha1);
+}
+
+void
+sha1_mid(hctx * h, const uschar * data)
+{
+native_sha1_mid(&h->sha1, data);
+}
+
+void
+sha1_end(hctx * h, const uschar * data, int len, uschar *digest)
+{
+native_sha1_end(&h->sha1, data, len, digest);
+}
+
+#else
+
+void
+sha1_start(hctx * h)
+{
+(void) exim_sha_init(h, HASH_SHA1);
+}
+
+void
+sha1_mid(hctx * h, const uschar * data)
+{
+exim_sha_update(h, data, 64);
+}
+
+void
+sha1_end(hctx * h, const uschar * data, int len, uschar *digest)
+{
+blob b;
+exim_sha_update(h, data, len);
+exim_sha_finish(h, &b);
+memcpy(digest, b.data, 20);
+}
+
+#endif
+
+
+
+
+
+
 /*************************************************
 **************************************************
 *             Stand-alone test program           *
 **************************************************
 *************************************************/
 
-#ifdef STAND_ALONE
+# ifdef STAND_ALONE
 
 /* Test values. The first 128 may contain binary zeros and have increasing
 length. */
@@ -525,8 +785,8 @@ printf("Checking sha1: %s-endian\n\n", (ctest[0] == 0x04)? "little" : "big");
 for (i = 0; i < sizeof(tests)/sizeof(uschar *); i ++)
   {
   printf("%d.\nShould be: %s\n", i, hashes[i]);
-  sha1_start(&base);
-  sha1_end(&base, tests[i], (i <= 128)? i : strlen(tests[i]), digest);
+  native_sha1_start(&base);
+  native_sha1_end(&base, tests[i], (i <= 128)? i : strlen(tests[i]), digest);
   for (j = 0; j < 20; j++) sprintf(s+2*j, "%02X", digest[j]);
   printf("Computed:  %s\n", s);
   if (strcmp(s, hashes[i]) != 0) printf("*** No match ***\n");
@@ -540,13 +800,13 @@ memset(ctest, 'a', 1000000);
 
 printf("1 000 000 repetitions of 'a'\n");
 printf("Should be: %s\n", atest);
-sha1_start(&base);
-sha1_end(&base, ctest, 1000000, digest);
+native_sha1_start(&base);
+native_sha1_end(&base, ctest, 1000000, digest);
 for (j = 0; j < 20; j++) sprintf(s+2*j, "%02X", digest[j]);
 printf("Computed:  %s\n", s);
 if (strcmp(s, atest) != 0) printf("*** No match ***\n");
 
 }
-#endif
+# endif        /*STAND_ALONE*/
 
-/* End of sha1.c */
+/* End of File */