commit 315bf9d: [Rework] Lua_cryptobox: Allow to store output of the hash function

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Jul 3 11:28:06 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-07-03 12:23:35 +0100
URL: https://github.com/rspamd/rspamd/commit/315bf9d19c5a3538e4df38bff853dc473e343384

[Rework] Lua_cryptobox: Allow to store output of the hash function

---
 src/lua/lua_cryptobox.c | 92 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 60 insertions(+), 32 deletions(-)

diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c
index ac3a93671..425818977 100644
--- a/src/lua/lua_cryptobox.c
+++ b/src/lua/lua_cryptobox.c
@@ -37,8 +37,9 @@
 
 #include <stdalign.h>
 
+
 enum lua_cryptobox_hash_type {
-	LUA_CRYPTOBOX_HASH_BLAKE2,
+	LUA_CRYPTOBOX_HASH_BLAKE2 = 0,
 	LUA_CRYPTOBOX_HASH_SSL,
 	LUA_CRYPTOBOX_HASH_XXHASH64,
 	LUA_CRYPTOBOX_HASH_XXHASH32,
@@ -53,8 +54,11 @@ struct rspamd_lua_cryptobox_hash {
 		rspamd_cryptobox_fast_hash_state_t *fh;
 	} content;
 
-	unsigned type:7;
-	unsigned is_finished:1;
+	unsigned char out[rspamd_cryptobox_HASHBYTES];
+
+	uint8_t type;
+	uint8_t out_len;
+	uint8_t is_finished;
 
 	ref_entry_t ref;
 };
@@ -1006,6 +1010,7 @@ rspamd_lua_hash_create (const gchar *type)
 		if (g_ascii_strcasecmp (type, "md5") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_SSL;
 			h->content.c = EVP_MD_CTX_create ();
+			h->out_len = EVP_MD_size (EVP_md5 ());
 			/* Should never ever be used for crypto/security purposes! */
 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
 			EVP_MD_CTX_set_flags (h->content.c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
@@ -1016,6 +1021,7 @@ rspamd_lua_hash_create (const gchar *type)
 					g_ascii_strcasecmp (type, "sha") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_SSL;
 			h->content.c = EVP_MD_CTX_create ();
+			h->out_len = EVP_MD_size (EVP_sha1 ());
 			/* Should never ever be used for crypto/security purposes! */
 #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
 			EVP_MD_CTX_set_flags (h->content.c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
@@ -1025,16 +1031,19 @@ rspamd_lua_hash_create (const gchar *type)
 		else if (g_ascii_strcasecmp (type, "sha256") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_SSL;
 			h->content.c = EVP_MD_CTX_create ();
+			h->out_len = EVP_MD_size (EVP_sha256 ());
 			EVP_DigestInit (h->content.c, EVP_sha256 ());
 		}
 		else if (g_ascii_strcasecmp (type, "sha512") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_SSL;
 			h->content.c = EVP_MD_CTX_create ();
+			h->out_len = EVP_MD_size (EVP_sha512 ());
 			EVP_DigestInit (h->content.c, EVP_sha512 ());
 		}
 		else if (g_ascii_strcasecmp (type, "sha384") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_SSL;
 			h->content.c = EVP_MD_CTX_create ();
+			h->out_len = EVP_MD_size (EVP_sha384 ());
 			EVP_DigestInit (h->content.c, EVP_sha384 ());
 		}
 		else if (g_ascii_strcasecmp (type, "blake2") == 0) {
@@ -1042,6 +1051,7 @@ rspamd_lua_hash_create (const gchar *type)
 			(void) !posix_memalign ((void **)&h->content.h, _Alignof (rspamd_cryptobox_hash_state_t),
 					sizeof (*h->content.h));
 			g_assert (h->content.h != NULL);
+			h->out_len = rspamd_cryptobox_HASHBYTES;
 			rspamd_cryptobox_hash_init (h->content.h, NULL, 0);
 		}
 		else if (g_ascii_strcasecmp (type, "xxh64") == 0) {
@@ -1049,24 +1059,28 @@ rspamd_lua_hash_create (const gchar *type)
 			h->content.fh = g_malloc0 (sizeof (*h->content.fh));
 			rspamd_cryptobox_fast_hash_init_specific (h->content.fh,
 					RSPAMD_CRYPTOBOX_XXHASH64, 0);
+			h->out_len = sizeof (guint64);
 		}
 		else if (g_ascii_strcasecmp (type, "xxh32") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_XXHASH32;
 			h->content.fh = g_malloc0 (sizeof (*h->content.fh));
 			rspamd_cryptobox_fast_hash_init_specific (h->content.fh,
 					RSPAMD_CRYPTOBOX_XXHASH32, 0);
+			h->out_len = sizeof (guint32);
 		}
 		else if (g_ascii_strcasecmp (type, "mum") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_MUM;
 			h->content.fh = g_malloc0 (sizeof (*h->content.fh));
 			rspamd_cryptobox_fast_hash_init_specific (h->content.fh,
 					RSPAMD_CRYPTOBOX_MUMHASH, 0);
+			h->out_len = sizeof (guint64);
 		}
 		else if (g_ascii_strcasecmp (type, "t1ha") == 0) {
 			h->type = LUA_CRYPTOBOX_HASH_T1HA;
 			h->content.fh = g_malloc0 (sizeof (*h->content.fh));
 			rspamd_cryptobox_fast_hash_init_specific (h->content.fh,
 					RSPAMD_CRYPTOBOX_T1HA, 0);
+			h->out_len = sizeof (guint64);
 		}
 		else {
 			g_free (h);
@@ -1075,11 +1089,13 @@ rspamd_lua_hash_create (const gchar *type)
 		}
 	}
 	else {
+		/* Default hash type */
 		h->type = LUA_CRYPTOBOX_HASH_BLAKE2;
 		(void) !posix_memalign ((void **)&h->content.h, _Alignof (rspamd_cryptobox_hash_state_t),
 				sizeof (*h->content.h));
 		g_assert (h->content.h != NULL);
 		rspamd_cryptobox_hash_init (h->content.h, NULL, 0);
+		h->out_len = rspamd_cryptobox_HASHBYTES;
 	}
 
 	return h;
@@ -1336,27 +1352,29 @@ lua_cryptobox_hash_reset (lua_State *L)
 }
 
 static void
-lua_cryptobox_hash_finish (struct rspamd_lua_cryptobox_hash *h,
-		guchar out[rspamd_cryptobox_HASHBYTES], guint *dlen)
+lua_cryptobox_hash_finish (struct rspamd_lua_cryptobox_hash *h)
 {
 	guint64 ll;
+	guchar out[rspamd_cryptobox_HASHBYTES];
+	guint ssl_outlen = sizeof (out);
 
 	switch (h->type) {
 	case LUA_CRYPTOBOX_HASH_BLAKE2:
-		*dlen = rspamd_cryptobox_HASHBYTES;
 		rspamd_cryptobox_hash_final (h->content.h, out);
+		memcpy (h->out, out, sizeof (out));
 		break;
 	case LUA_CRYPTOBOX_HASH_SSL:
-
-		EVP_DigestFinal_ex (h->content.c, out, dlen);
+		EVP_DigestFinal_ex (h->content.c, out, &ssl_outlen);
+		h->out_len = ssl_outlen;
+		g_assert (ssl_outlen <= sizeof (h->out));
+		memcpy (h->out, out, ssl_outlen);
 		break;
 	case LUA_CRYPTOBOX_HASH_XXHASH64:
 	case LUA_CRYPTOBOX_HASH_XXHASH32:
 	case LUA_CRYPTOBOX_HASH_MUM:
 	case LUA_CRYPTOBOX_HASH_T1HA:
 		ll = rspamd_cryptobox_fast_hash_final (h->content.fh);
-		memcpy (out, &ll, sizeof (ll));
-		*dlen = sizeof (ll);
+		memcpy (h->out, &ll, sizeof (ll));
 		break;
 	default:
 		g_assert_not_reached ();
@@ -1375,15 +1393,17 @@ lua_cryptobox_hash_hex (lua_State *L)
 {
 	LUA_TRACE_POINT;
 	struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash (L, 1);
-	guchar out[rspamd_cryptobox_HASHBYTES],
-		out_hex[rspamd_cryptobox_HASHBYTES * 2 + 1], *r;
+	guchar out_hex[rspamd_cryptobox_HASHBYTES * 2 + 1], *r;
 	guint dlen;
 
-	if (h && !h->is_finished) {
-		memset (out_hex, 0, sizeof (out_hex));
+	if (h) {
+		if (!h->is_finished) {
+			lua_cryptobox_hash_finish (h);
+		}
 
-		lua_cryptobox_hash_finish (h, out, &dlen);
-		r = out;
+		memset (out_hex, 0, sizeof (out_hex));
+		r = h->out;
+		dlen = h->out_len;
 
 		if (lua_isnumber (L, 2)) {
 			guint lim = lua_tonumber (L, 2);
@@ -1396,7 +1416,6 @@ lua_cryptobox_hash_hex (lua_State *L)
 
 		rspamd_encode_hex_buf (r, dlen, out_hex, sizeof (out_hex));
 		lua_pushstring (L, out_hex);
-
 	}
 	else {
 		return luaL_error (L, "invalid arguments");
@@ -1416,11 +1435,10 @@ lua_cryptobox_hash_base32 (lua_State *L)
 {
 	LUA_TRACE_POINT;
 	struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash (L, 1);
-	guchar out[rspamd_cryptobox_HASHBYTES],
-		out_b32[rspamd_cryptobox_HASHBYTES * 2], *r;
+	guchar out_b32[rspamd_cryptobox_HASHBYTES * 2], *r;
 	guint dlen;
 
-	if (h && !h->is_finished) {
+	if (h) {
 		enum rspamd_base32_type btype = RSPAMD_BASE32_DEFAULT;
 
 		if (lua_type (L, 2) == LUA_TSTRING) {
@@ -1431,9 +1449,13 @@ lua_cryptobox_hash_base32 (lua_State *L)
 			}
 		}
 
+		if (!h->is_finished) {
+			lua_cryptobox_hash_finish (h);
+		}
+
 		memset (out_b32, 0, sizeof (out_b32));
-		lua_cryptobox_hash_finish (h, out, &dlen);
-		r = out;
+		r = h->out;
+		dlen = h->out_len;
 
 		if (lua_isnumber (L, 2)) {
 			guint lim = lua_tonumber (L, 2);
@@ -1446,7 +1468,6 @@ lua_cryptobox_hash_base32 (lua_State *L)
 
 		rspamd_encode_base32_buf (r, dlen, out_b32, sizeof (out_b32), btype);
 		lua_pushstring (L, out_b32);
-		h->is_finished = TRUE;
 	}
 	else {
 		return luaL_error (L, "invalid arguments");
@@ -1465,13 +1486,17 @@ lua_cryptobox_hash_base64 (lua_State *L)
 {
 	LUA_TRACE_POINT;
 	struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash (L, 1);
-	guchar out[rspamd_cryptobox_HASHBYTES], *b64, *r;
+	guchar *b64, *r;
 	gsize len;
 	guint dlen;
 
-	if (h && !h->is_finished) {
-		lua_cryptobox_hash_finish (h, out, &dlen);
-		r = out;
+	if (h) {
+		if (!h->is_finished) {
+			lua_cryptobox_hash_finish (h);
+		}
+
+		r = h->out;
+		dlen = h->out_len;
 
 		if (lua_isnumber (L, 2)) {
 			guint lim = lua_tonumber (L, 2);
@@ -1485,7 +1510,6 @@ lua_cryptobox_hash_base64 (lua_State *L)
 		b64 = rspamd_encode_base64 (r, dlen, 0, &len);
 		lua_pushlstring (L, b64, len);
 		g_free (b64);
-		h->is_finished = TRUE;
 	}
 	else {
 		return luaL_error (L, "invalid arguments");
@@ -1504,12 +1528,16 @@ lua_cryptobox_hash_bin (lua_State *L)
 {
 	LUA_TRACE_POINT;
 	struct rspamd_lua_cryptobox_hash *h = lua_check_cryptobox_hash (L, 1);
-	guchar out[rspamd_cryptobox_HASHBYTES], *r;
+	guchar *r;
 	guint dlen;
 
-	if (h && !h->is_finished) {
-		lua_cryptobox_hash_finish (h, out, &dlen);
-		r = out;
+	if (h) {
+		if (!h->is_finished) {
+			lua_cryptobox_hash_finish (h);
+		}
+
+		r = h->out;
+		dlen = h->out_len;
 
 		if (lua_isnumber (L, 2)) {
 			guint lim = lua_tonumber (L, 2);


More information about the Commits mailing list