]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Implement IUF interface for specific fast hashes
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 23 Apr 2019 17:16:49 +0000 (18:16 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 23 Apr 2019 17:16:49 +0000 (18:16 +0100)
src/libcryptobox/cryptobox.c
src/libcryptobox/cryptobox.h

index 1dcd188386634071bbd1076a1d877f9044e5ca60..88b8044ca919f12a97c868f127b0202e99f567b1 100644 (file)
@@ -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;
 }
 
 /**
index 016e58fc294a65d14f55fadb8b92677f51332921..b78830ae1195ee2a76c82bbe432ada2f58b082b7 100644 (file)
@@ -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
  */