commit 1703580: [Feature] Implement IUF interface for specific fast hashes

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Apr 23 17:35:05 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-04-23 18:16:49 +0100
URL: https://github.com/rspamd/rspamd/commit/1703580be7327e219138b6b25716e6cdf142cca5

[Feature] Implement IUF interface for specific fast hashes

---
 src/libcryptobox/cryptobox.c | 167 +++++++++++++++++++++++++++++++++++++++++--
 src/libcryptobox/cryptobox.h |  29 +++++---
 2 files changed, 180 insertions(+), 16 deletions(-)

diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c
index 1dcd18838..88b8044ca 100644
--- a/src/libcryptobox/cryptobox.c
+++ b/src/libcryptobox/cryptobox.c
@@ -1487,31 +1487,184 @@ void rspamd_cryptobox_hash (guchar *out,
 	rspamd_cryptobox_hash_final (&st, out);
 }
 
-G_STATIC_ASSERT (sizeof (t1ha_context_t) ==
-		sizeof (rspamd_cryptobox_fast_hash_state_t));
+G_STATIC_ASSERT (sizeof (t1ha_context_t) <=
+		sizeof (((rspamd_cryptobox_fast_hash_state_t *)NULL)->opaque));
+G_STATIC_ASSERT (sizeof (XXH64_state_t) <=
+				 sizeof (((rspamd_cryptobox_fast_hash_state_t *)NULL)->opaque));
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wgnu"
+G_STATIC_ASSERT(G_ALIGNOF (t1ha_context_t) <=
+		G_ALIGNOF (((rspamd_cryptobox_fast_hash_state_t *)NULL)->opaque));
+#pragma GCC diagnostic pop
+#endif
+
+struct RSPAMD_ALIGNED(16) _mum_iuf {
+	union {
+		gint64 ll;
+		unsigned char b[sizeof (guint64)];
+	} buf;
+	gint64 h;
+	unsigned rem;
+};
 
 void
 rspamd_cryptobox_fast_hash_init (rspamd_cryptobox_fast_hash_state_t *st,
 		guint64 seed)
 {
-	t1ha_context_t *rst = (t1ha_context_t *)st;
+	t1ha_context_t *rst = (t1ha_context_t *)st->opaque;
+	st->type = RSPAMD_CRYPTOBOX_T1HA;
 	t1ha2_init (rst, seed, 0);
 }
 
+void
+rspamd_cryptobox_fast_hash_init_specific (rspamd_cryptobox_fast_hash_state_t *st,
+										  enum rspamd_cryptobox_fast_hash_type type,
+										  guint64 seed)
+{
+	switch (type) {
+	case RSPAMD_CRYPTOBOX_T1HA:
+	case RSPAMD_CRYPTOBOX_HASHFAST:
+	case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT: {
+		t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
+		st->type = RSPAMD_CRYPTOBOX_T1HA;
+		t1ha2_init (rst, seed, 0);
+		break;
+	}
+	case RSPAMD_CRYPTOBOX_XXHASH64: {
+		XXH64_state_t *xst = (XXH64_state_t *)  st->opaque;
+		st->type = RSPAMD_CRYPTOBOX_XXHASH64;
+		XXH64_reset (xst, seed);
+		break;
+	}
+	case RSPAMD_CRYPTOBOX_XXHASH32:
+	{
+		XXH32_state_t *xst = (XXH32_state_t *)  st->opaque;
+		st->type = RSPAMD_CRYPTOBOX_XXHASH32;
+		XXH32_reset (xst, seed);
+		break;
+	}
+	case RSPAMD_CRYPTOBOX_MUMHASH: {
+		struct _mum_iuf *iuf = (struct _mum_iuf *)  st->opaque;
+		st->type = RSPAMD_CRYPTOBOX_MUMHASH;
+		iuf->h = seed;
+		iuf->buf.ll = 0;
+		iuf->rem = 0;
+		break;
+	}
+	}
+}
+
 void
 rspamd_cryptobox_fast_hash_update (rspamd_cryptobox_fast_hash_state_t *st,
 		const void *data, gsize len)
 {
-	t1ha_context_t *rst = (t1ha_context_t *)st;
-	t1ha2_update (rst, data, len);
+	if (G_LIKELY (st->type) == RSPAMD_CRYPTOBOX_T1HA) {
+		t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
+		t1ha2_update (rst, data, len);
+	}
+	else {
+		switch (st->type) {
+		case RSPAMD_CRYPTOBOX_XXHASH64: {
+			XXH64_state_t *xst = (XXH64_state_t *)  st->opaque;
+			XXH64_update (xst, data, len);
+			break;
+		}
+		case RSPAMD_CRYPTOBOX_XXHASH32:
+		{
+			XXH32_state_t *xst = (XXH32_state_t *)  st->opaque;
+			XXH32_update (xst, data, len);
+			break;
+		}
+		case RSPAMD_CRYPTOBOX_MUMHASH: {
+			struct _mum_iuf *iuf = (struct _mum_iuf *)  st->opaque;
+			gsize drem = len;
+			const guchar *p = data;
+
+			if (iuf->rem > 0) {
+				/* Process remainder */
+				if (drem >= iuf->rem) {
+					memcpy (iuf->buf.b + sizeof (iuf->buf.ll) - iuf->rem,
+							p, iuf->rem);
+					drem -= iuf->rem;
+					p += iuf->rem;
+					iuf->h = mum_hash_step (iuf->h, iuf->buf.ll);
+					iuf->rem = 0;
+				}
+				else {
+					memcpy (iuf->buf.b + sizeof (iuf->buf.ll) - iuf->rem, p, drem);
+					iuf->rem -= drem;
+					drem = 0;
+				}
+			}
+
+			while (drem >= sizeof (iuf->buf.ll)) {
+				memcpy (iuf->buf.b, p, sizeof (iuf->buf.ll));
+				iuf->h = mum_hash_step (iuf->h, iuf->buf.ll);
+				drem -= sizeof (iuf->buf.ll);
+				p += sizeof (iuf->buf.ll);
+			}
+
+			/* Leftover */
+			if (drem > 0) {
+				iuf->rem = sizeof (guint64) - drem;
+				iuf->buf.ll = 0;
+				memcpy (iuf->buf.b, p, drem);
+			}
+			break;
+		}
+		case RSPAMD_CRYPTOBOX_T1HA:
+		case RSPAMD_CRYPTOBOX_HASHFAST:
+		case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT: {
+			t1ha_context_t *rst = (t1ha_context_t *)  st->opaque;
+			t1ha2_update (rst, data, len);
+			break;
+		}
+		}
+	}
 }
 
 guint64
 rspamd_cryptobox_fast_hash_final (rspamd_cryptobox_fast_hash_state_t *st)
 {
-	t1ha_context_t *rst = (t1ha_context_t *)st;
+	guint64 ret;
 
-	return t1ha2_final (rst, NULL);
+	if (G_LIKELY (st->type) == RSPAMD_CRYPTOBOX_T1HA) {
+		t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
+
+		return t1ha2_final (rst, NULL);
+	}
+	else {
+		switch (st->type) {
+		case RSPAMD_CRYPTOBOX_XXHASH64: {
+			XXH64_state_t *xst = (XXH64_state_t *)  st->opaque;
+			ret = XXH64_digest (xst);
+			break;
+		}
+		case RSPAMD_CRYPTOBOX_XXHASH32: {
+			XXH32_state_t *xst = (XXH32_state_t *)  st->opaque;
+			ret = XXH32_digest (xst);
+			break;
+		}
+		case RSPAMD_CRYPTOBOX_MUMHASH: {
+			struct _mum_iuf *iuf = (struct _mum_iuf *)  st->opaque;
+			iuf->h = mum_hash_step (iuf->h, iuf->buf.ll);
+			ret = mum_hash_finish (iuf->h);
+			break;
+		}
+		case RSPAMD_CRYPTOBOX_T1HA:
+		case RSPAMD_CRYPTOBOX_HASHFAST:
+		case RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT: {
+			t1ha_context_t *rst = (t1ha_context_t *) st->opaque;
+
+			ret = t1ha2_final (rst, NULL);
+			break;
+		}
+		}
+	}
+
+	return ret;
 }
 
 /**
diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h
index 016e58fc2..b78830ae1 100644
--- a/src/libcryptobox/cryptobox.h
+++ b/src/libcryptobox/cryptobox.h
@@ -343,9 +343,19 @@ void rspamd_cryptobox_hash (guchar *out,
 		const guchar *key,
 		gsize keylen);
 
+enum rspamd_cryptobox_fast_hash_type {
+	RSPAMD_CRYPTOBOX_XXHASH64 = 0,
+	RSPAMD_CRYPTOBOX_XXHASH32,
+	RSPAMD_CRYPTOBOX_MUMHASH,
+	RSPAMD_CRYPTOBOX_T1HA,
+	RSPAMD_CRYPTOBOX_HASHFAST,
+	RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT
+};
+
 /* Non crypto hash IUF interface */
 typedef struct RSPAMD_ALIGNED(16) rspamd_cryptobox_fast_hash_state_s  {
-	unsigned char opaque[64 + sizeof (size_t) + sizeof (uint64_t)];
+	RSPAMD_ALIGNED(16) guint64 opaque[11];
+	enum rspamd_cryptobox_fast_hash_type type;
 } rspamd_cryptobox_fast_hash_state_t;
 
 /**
@@ -356,6 +366,15 @@ typedef struct RSPAMD_ALIGNED(16) rspamd_cryptobox_fast_hash_state_s  {
 void rspamd_cryptobox_fast_hash_init (rspamd_cryptobox_fast_hash_state_t *st,
 		guint64 seed);
 
+/**
+ * Init cryptobox hash state using key if needed, `st` must point to the buffer
+ * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
+ * non-keyed hash is generated
+ */
+void rspamd_cryptobox_fast_hash_init_specific (rspamd_cryptobox_fast_hash_state_t *st,
+											   enum rspamd_cryptobox_fast_hash_type type,
+											   guint64 seed);
+
 /**
  * Update hash with data portion
  */
@@ -373,14 +392,6 @@ guint64 rspamd_cryptobox_fast_hash_final (rspamd_cryptobox_fast_hash_state_t *st
 guint64 rspamd_cryptobox_fast_hash (const void *data,
 		gsize len, guint64 seed);
 
-enum rspamd_cryptobox_fast_hash_type {
-	RSPAMD_CRYPTOBOX_XXHASH64 = 0,
-	RSPAMD_CRYPTOBOX_XXHASH32,
-	RSPAMD_CRYPTOBOX_MUMHASH,
-	RSPAMD_CRYPTOBOX_T1HA,
-	RSPAMD_CRYPTOBOX_HASHFAST,
-	RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT
-};
 /**
  * Platform independent version
  */


More information about the Commits mailing list