commit 8f70f5e: [Feature] Lua_cryptobox: Add keyed ssl hash functions via HMAC
Vsevolod Stakhov
vsevolod at highsecure.ru
Tue Aug 10 10:21:04 UTC 2021
Author: Vsevolod Stakhov
Date: 2021-08-10 11:18:33 +0100
URL: https://github.com/rspamd/rspamd/commit/8f70f5e4b465ace44590ad233a223639e5a5e861 (HEAD -> master)
[Feature] Lua_cryptobox: Add keyed ssl hash functions via HMAC
---
src/lua/lua_cryptobox.c | 184 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 155 insertions(+), 29 deletions(-)
diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c
index 788f2e1df..f712fad0c 100644
--- a/src/lua/lua_cryptobox.c
+++ b/src/lua/lua_cryptobox.c
@@ -36,11 +36,13 @@
#include "libutil/ref.h"
#include <stdalign.h>
+#include <openssl/hmac.h>
enum lua_cryptobox_hash_type {
LUA_CRYPTOBOX_HASH_BLAKE2 = 0,
LUA_CRYPTOBOX_HASH_SSL,
+ LUA_CRYPTOBOX_HASH_HMAC,
LUA_CRYPTOBOX_HASH_XXHASH64,
LUA_CRYPTOBOX_HASH_XXHASH32,
LUA_CRYPTOBOX_HASH_MUM,
@@ -51,6 +53,7 @@ struct rspamd_lua_cryptobox_hash {
union {
rspamd_cryptobox_hash_state_t *h;
EVP_MD_CTX *c;
+ HMAC_CTX *hmac_c;
rspamd_cryptobox_fast_hash_state_t *fh;
} content;
@@ -83,6 +86,7 @@ LUA_FUNCTION_DEF (cryptobox_signature, base64);
LUA_FUNCTION_DEF (cryptobox_signature, bin);
LUA_FUNCTION_DEF (cryptobox_hash, create);
LUA_FUNCTION_DEF (cryptobox_hash, create_specific);
+LUA_FUNCTION_DEF (cryptobox_hash, create_specific_keyed);
LUA_FUNCTION_DEF (cryptobox_hash, create_keyed);
LUA_FUNCTION_DEF (cryptobox_hash, update);
LUA_FUNCTION_DEF (cryptobox_hash, reset);
@@ -178,6 +182,7 @@ static const struct luaL_reg cryptoboxhashlib_f[] = {
LUA_INTERFACE_DEF (cryptobox_hash, create),
LUA_INTERFACE_DEF (cryptobox_hash, create_keyed),
LUA_INTERFACE_DEF (cryptobox_hash, create_specific),
+ LUA_INTERFACE_DEF (cryptobox_hash, create_specific_keyed),
{NULL, NULL}
};
@@ -964,6 +969,9 @@ rspamd_lua_hash_update (struct rspamd_lua_cryptobox_hash *h,
case LUA_CRYPTOBOX_HASH_SSL:
EVP_DigestUpdate (h->content.c, p, len);
break;
+ case LUA_CRYPTOBOX_HASH_HMAC:
+ HMAC_Update (h->content.hmac_c, p, len);
+ break;
case LUA_CRYPTOBOX_HASH_XXHASH64:
case LUA_CRYPTOBOX_HASH_XXHASH32:
case LUA_CRYPTOBOX_HASH_MUM:
@@ -987,6 +995,14 @@ lua_cryptobox_hash_dtor (struct rspamd_lua_cryptobox_hash *h)
#endif
EVP_MD_CTX_destroy (h->content.c);
}
+ else if (h->type == LUA_CRYPTOBOX_HASH_HMAC) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ HMAC_CTX_cleanup (h->content.hmac_c);
+ g_free (h->content.hmac_c);
+#else
+ HMAC_CTX_free (h->content.hmac_c);
+#endif
+ }
else if (h->type == LUA_CRYPTOBOX_HASH_BLAKE2) {
rspamd_explicit_memzero (h->content.h, sizeof (*h->content.h));
free (h->content.h); /* Allocated by posix_memalign */
@@ -1013,6 +1029,50 @@ rspamd_lua_hash_init_default (struct rspamd_lua_cryptobox_hash *h,
h->out_len = rspamd_cryptobox_HASHBYTES;
}
+static void
+rspamd_lua_ssl_hash_create (struct rspamd_lua_cryptobox_hash *h, const EVP_MD *htype,
+ bool insecure)
+{
+ h->type = LUA_CRYPTOBOX_HASH_SSL;
+ h->content.c = EVP_MD_CTX_create ();
+ h->out_len = EVP_MD_size (htype);
+
+ if (insecure) {
+ /* 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);
+#endif
+ }
+
+ EVP_DigestInit_ex (h->content.c, htype, NULL);
+}
+
+static void
+rspamd_lua_ssl_hmac_create (struct rspamd_lua_cryptobox_hash *h, const EVP_MD *htype,
+ const gchar *key, gsize keylen,
+ bool insecure)
+{
+ h->type = LUA_CRYPTOBOX_HASH_HMAC;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ h->content.hmac_c = g_malloc0 (sizeof(*h->content.hmac_c));
+#else
+ h->content.hmac_c = HMAC_CTX_new ();
+#endif
+ h->out_len = EVP_MD_size (htype);
+
+#if OPENSSL_VERSION_NUMBER > 0x10100000L
+ if (insecure) {
+ /* Should never ever be used for crypto/security purposes! */
+#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+ HMAC_CTX_set_flags(h->content.hmac_c, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ }
+#endif
+
+ HMAC_Init_ex (h->content.hmac_c, key, keylen, htype, NULL);
+}
+
static struct rspamd_lua_cryptobox_hash *
rspamd_lua_hash_create (const gchar *type, const gchar *key, gsize keylen)
{
@@ -1023,43 +1083,45 @@ rspamd_lua_hash_create (const gchar *type, const gchar *key, gsize keylen)
if (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);
-#endif
- EVP_DigestInit_ex (h->content.c, EVP_md5 (), NULL);
+ if (keylen > 0) {
+ rspamd_lua_ssl_hmac_create(h, EVP_md5(), key, keylen, true);
+ }
+ else {
+ rspamd_lua_ssl_hash_create(h, EVP_md5(), true);
+ }
}
else if (g_ascii_strcasecmp (type, "sha1") == 0 ||
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);
-#endif
- EVP_DigestInit_ex (h->content.c, EVP_sha1 (), NULL);
+ if (keylen > 0) {
+ rspamd_lua_ssl_hmac_create(h, EVP_sha1(), key, keylen, true);
+ }
+ else {
+ rspamd_lua_ssl_hash_create(h, EVP_sha1(), true);
+ }
}
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 ());
+ if (keylen > 0) {
+ rspamd_lua_ssl_hmac_create(h, EVP_sha256(), key, keylen, true);
+ }
+ else {
+ rspamd_lua_ssl_hash_create(h, EVP_sha256(), true);
+ }
}
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 ());
+ if (keylen > 0) {
+ rspamd_lua_ssl_hmac_create(h, EVP_sha512(), key, keylen, true);
+ }
+ else {
+ rspamd_lua_ssl_hash_create(h, EVP_sha512(), true);
+ }
}
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 ());
+ if (keylen > 0) {
+ rspamd_lua_ssl_hmac_create(h, EVP_sha384(), key, keylen, true);
+ }
+ else {
+ rspamd_lua_ssl_hash_create(h, EVP_sha384(), true);
+ }
}
else if (g_ascii_strcasecmp (type, "xxh64") == 0) {
h->type = LUA_CRYPTOBOX_HASH_XXHASH64;
@@ -1235,7 +1297,57 @@ lua_cryptobox_hash_create_keyed (lua_State *L)
}
if (s) {
- rspamd_cryptobox_hash_update (h->content.h, s, len);
+ rspamd_lua_hash_update (h, s, len);
+ }
+
+ ph = lua_newuserdata (L, sizeof (void *));
+ *ph = h;
+ rspamd_lua_setclass (L, "rspamd{cryptobox_hash}", -1);
+ }
+ else {
+ return luaL_error (L, "invalid arguments");
+ }
+
+ return 1;
+}
+
+/***
+ * @function rspamd_cryptobox_hash.create_specific_keyed(key, type, [string])
+ * Creates new hash context with specified key
+ * @param {string} key key
+ * @return {cryptobox_hash} hash object
+ */
+static gint
+lua_cryptobox_hash_create_specific_keyed (lua_State *L)
+{
+ LUA_TRACE_POINT;
+ struct rspamd_lua_cryptobox_hash *h, **ph;
+ const gchar *key, *s = NULL, *type = luaL_checkstring (L, 2);
+ struct rspamd_lua_text *t;
+ gsize len = 0;
+ gsize keylen;
+
+ key = luaL_checklstring (L, 1, &keylen);
+
+ if (key != NULL && type != NULL) {
+ h = rspamd_lua_hash_create (type, key, keylen);
+
+ if (lua_type (L, 3) == LUA_TSTRING) {
+ s = lua_tolstring (L, 3, &len);
+ }
+ else if (lua_type (L, 3) == LUA_TUSERDATA) {
+ t = lua_check_text (L, 3);
+
+ if (!t) {
+ return luaL_error (L, "invalid arguments");
+ }
+
+ s = t->start;
+ len = t->len;
+ }
+
+ if (s) {
+ rspamd_lua_hash_update (h, s, len);
}
ph = lua_newuserdata (L, sizeof (void *));
@@ -1327,6 +1439,14 @@ lua_cryptobox_hash_reset (lua_State *L)
case LUA_CRYPTOBOX_HASH_SSL:
EVP_DigestInit (h->content.c, EVP_MD_CTX_md (h->content.c));
break;
+ case LUA_CRYPTOBOX_HASH_HMAC:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ /* Old openssl is awesome... */
+ HMAC_Init_ex (h->content.hmac_c, NULL, 0, h->content.hmac_c->md, NULL);
+#else
+ HMAC_CTX_reset (h->content.hmac_c);
+#endif
+ break;
case LUA_CRYPTOBOX_HASH_XXHASH64:
rspamd_cryptobox_fast_hash_init_specific (h->content.fh,
RSPAMD_CRYPTOBOX_XXHASH64, 0);
@@ -1378,6 +1498,12 @@ lua_cryptobox_hash_finish (struct rspamd_lua_cryptobox_hash *h)
g_assert (ssl_outlen <= sizeof (h->out));
memcpy (h->out, out, ssl_outlen);
break;
+ case LUA_CRYPTOBOX_HASH_HMAC:
+ HMAC_Final (h->content.hmac_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:
More information about the Commits
mailing list