From 6ad9132909d8a43cf484f70aa990daccc8e2eb2b Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 6 May 2020 17:08:22 +0100 Subject: [PATCH] [Feature] Allow to specify nonces manually --- src/lua/lua_cryptobox.c | 90 +++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 21 deletions(-) diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c index b0f5f0bac..ac3a93671 100644 --- a/src/lua/lua_cryptobox.c +++ b/src/lua/lua_cryptobox.c @@ -2542,20 +2542,21 @@ lua_cryptobox_secretbox_gc (lua_State *L) } /*** - * @method rspamd_cryptobox_secretbox:encrypt(input) + * @method rspamd_cryptobox_secretbox:encrypt(input, [nonce]) * Encrypts data using secretbox. MAC is prepended to the message * @param {string/text} input input to encrypt + * @param {string/text} nonce optional nonce (must be 1 - 192 bits length) * @param {table} params optional parameters - NYI - * @return {rspamd_text},{rspamd_text} nonce + output with mac + * @return {rspamd_text},{rspamd_text} output with mac + nonce or just output if nonce is there */ static gint lua_cryptobox_secretbox_encrypt (lua_State *L) { - const gchar *in; - gsize inlen; + const gchar *in, *nonce; + gsize inlen, nlen; struct rspamd_lua_cryptobox_secretbox *sbox = lua_check_cryptobox_secretbox (L, 1); - struct rspamd_lua_text *out, *nonce; + struct rspamd_lua_text *out; if (sbox == NULL) { return luaL_error (L, "invalid arguments"); @@ -2578,18 +2579,59 @@ lua_cryptobox_secretbox_encrypt (lua_State *L) return luaL_error (L, "invalid arguments; userdata or string are expected"); } - nonce = lua_new_text (L, NULL, crypto_secretbox_NONCEBYTES, TRUE); - out = lua_new_text (L, NULL, inlen + crypto_secretbox_MACBYTES, - TRUE); + /* Nonce part */ + if (!lua_isnoneornil (L, 3)) { + if (lua_isstring (L, 3)) { + nonce = lua_tolstring (L, 3, &nlen); + } + else if (lua_isuserdata (L, 3)) { + struct rspamd_lua_text *t = lua_check_text (L, 3); - randombytes_buf ((guchar *)nonce->start, nonce->len); - crypto_secretbox_easy ((guchar *)out->start, in, inlen, nonce->start, sbox->sk); + if (!t) { + return luaL_error (L, "invalid arguments; userdata is not text"); + } - return 2; + nonce = t->start; + nlen = t->len; + } + else { + return luaL_error (L, "invalid arguments; userdata or string are expected"); + } + + if (nlen < 1 || nlen > crypto_secretbox_NONCEBYTES) { + return luaL_error (L, "bad nonce"); + } + + guchar real_nonce[crypto_secretbox_NONCEBYTES]; + + memset (real_nonce, 0, sizeof (real_nonce)); + memcpy (real_nonce, nonce, nlen); + + out = lua_new_text (L, NULL, inlen + crypto_secretbox_MACBYTES, + TRUE); + crypto_secretbox_easy ((guchar *)out->start, in, inlen, + nonce, sbox->sk); + + return 1; + } + else { + /* Random nonce */ + struct rspamd_lua_text *random_nonce; + + out = lua_new_text (L, NULL, inlen + crypto_secretbox_MACBYTES, + TRUE); + random_nonce = lua_new_text (L, NULL, crypto_secretbox_NONCEBYTES, TRUE); + + randombytes_buf ((guchar *)random_nonce->start, random_nonce->len); + crypto_secretbox_easy ((guchar *)out->start, in, inlen, + random_nonce->start, sbox->sk); + + return 2; /* output + random nonce */ + } } /*** - * @method rspamd_cryptobox_secretbox:decrypt(nonce, input) + * @method rspamd_cryptobox_secretbox:decrypt(input, nonce) * Decrypts data using secretbox * @param {string/text} nonce nonce used to encrypt * @param {string/text} input input to decrypt @@ -2609,9 +2651,9 @@ lua_cryptobox_secretbox_decrypt (lua_State *L) return luaL_error (L, "invalid arguments"); } - /* Nonce argument */ + /* Input argument */ if (lua_isstring (L, 2)) { - nonce = lua_tolstring (L, 2, &nlen); + in = lua_tolstring (L, 2, &inlen); } else if (lua_isuserdata (L, 2)) { struct rspamd_lua_text *t = lua_check_text (L, 2); @@ -2620,16 +2662,16 @@ lua_cryptobox_secretbox_decrypt (lua_State *L) return luaL_error (L, "invalid arguments; userdata is not text"); } - nonce = t->start; - nlen = t->len; + in = t->start; + inlen = t->len; } else { return luaL_error (L, "invalid arguments; userdata or string are expected"); } - /* Input argument */ + /* Nonce argument */ if (lua_isstring (L, 3)) { - in = lua_tolstring (L, 3, &inlen); + nonce = lua_tolstring (L, 3, &nlen); } else if (lua_isuserdata (L, 3)) { struct rspamd_lua_text *t = lua_check_text (L, 3); @@ -2638,14 +2680,15 @@ lua_cryptobox_secretbox_decrypt (lua_State *L) return luaL_error (L, "invalid arguments; userdata is not text"); } - in = t->start; - inlen = t->len; + nonce = t->start; + nlen = t->len; } else { return luaL_error (L, "invalid arguments; userdata or string are expected"); } - if (nlen != crypto_secretbox_NONCEBYTES) { + + if (nlen < 1 || nlen > crypto_secretbox_NONCEBYTES) { lua_pushboolean (L, false); lua_pushstring (L, "invalid nonce"); return 2; @@ -2657,6 +2700,11 @@ lua_cryptobox_secretbox_decrypt (lua_State *L) return 2; } + guchar real_nonce[crypto_secretbox_NONCEBYTES]; + + memset (real_nonce, 0, sizeof (real_nonce)); + memcpy (real_nonce, nonce, nlen); + out = lua_new_text (L, NULL, inlen - crypto_secretbox_MACBYTES, TRUE); gint text_pos = lua_gettop (L); -- 2.39.5