From 5658e4bfd4045bf31b2ba9f4e2a31066dc252d67 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 5 Jun 2018 17:02:58 +0100 Subject: [PATCH] [Fix] Fix NIST signatures --- src/libcryptobox/cryptobox.c | 5 +-- src/libcryptobox/cryptobox.h | 1 + src/libcryptobox/keypair.c | 2 +- src/libutil/map.c | 2 +- src/lua/lua_cryptobox.c | 65 ++++++++++++++++++++++++++++++------ src/rspamadm/signtool.c | 3 +- 6 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index b58f84418..99c91e3dd 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -576,6 +576,7 @@ rspamd_cryptobox_sign (guchar *sig, gsize *siglen_p, bool rspamd_cryptobox_verify (const guchar *sig, + gsize siglen, const guchar *m, gsize mlen, const rspamd_pk_t pk, @@ -584,6 +585,7 @@ rspamd_cryptobox_verify (const guchar *sig, bool ret = false; if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { + g_assert (siglen == rspamd_cryptobox_signature_bytes (RSPAMD_CRYPTOBOX_MODE_25519)); ret = ed25519_verify (sig, m, mlen, pk); } else { @@ -612,8 +614,7 @@ rspamd_cryptobox_verify (const guchar *sig, g_assert (EC_KEY_set_public_key (lk, ec_pub) == 1); /* ECDSA */ - ret = ECDSA_verify (0, h, sizeof (h), sig, - rspamd_cryptobox_signature_bytes (mode), lk) == 1; + ret = ECDSA_verify (0, h, sizeof (h), sig, siglen, lk) == 1; EC_KEY_free (lk); EVP_MD_CTX_destroy (sha_ctx); diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index e5cdb8f6c..1d48c06e5 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -214,6 +214,7 @@ void rspamd_cryptobox_sign (guchar *sig, gsize *siglen_p, * @return true if signature is valid, false otherwise */ bool rspamd_cryptobox_verify (const guchar *sig, + gsize siglen, const guchar *m, gsize mlen, const rspamd_pk_t pk, diff --git a/src/libcryptobox/keypair.c b/src/libcryptobox/keypair.c index 50e3614d9..21b497130 100644 --- a/src/libcryptobox/keypair.c +++ b/src/libcryptobox/keypair.c @@ -881,7 +881,7 @@ rspamd_keypair_verify (struct rspamd_cryptobox_pubkey *pk, return FALSE; } - if (!rspamd_cryptobox_verify (sig, data, len, + if (!rspamd_cryptobox_verify (sig, siglen, data, len, rspamd_cryptobox_pubkey_pk (pk, &pklen), pk->alg)) { g_set_error (err, rspamd_keypair_quark (), EPERM, "signature verification failed"); diff --git a/src/libutil/map.c b/src/libutil/map.c index 577933c25..2873b76f6 100644 --- a/src/libutil/map.c +++ b/src/libutil/map.c @@ -150,7 +150,7 @@ rspamd_map_check_sig_pk_mem (const guchar *sig, ret = FALSE; } - if (ret && !rspamd_cryptobox_verify (sig, input, inlen, + if (ret && !rspamd_cryptobox_verify (sig, siglen, input, inlen, rspamd_pubkey_get_pk (pk, NULL), RSPAMD_CRYPTOBOX_MODE_25519)) { msg_err_map ("can't verify signature for %s: incorrect signature", map->name); diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c index 0323fe098..6fa2aa997 100644 --- a/src/lua/lua_cryptobox.c +++ b/src/lua/lua_cryptobox.c @@ -585,7 +585,7 @@ lua_cryptobox_keypair_get_pk (lua_State *L) } /*** - * @function rspamd_cryptobox_signature.load(file) + * @function rspamd_cryptobox_signature.load(file, [alg = 'curve25519']) * Loads signature from raw file * @param {string} file filename to load * @return {cryptobox_signature} new signature @@ -598,6 +598,7 @@ lua_cryptobox_signature_load (lua_State *L) gpointer data; int fd; struct stat st; + enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519; filename = luaL_checkstring (L, 1); if (filename != NULL) { @@ -608,7 +609,6 @@ lua_cryptobox_signature_load (lua_State *L) lua_pushnil (L); } else { - sig = g_malloc (sizeof (rspamd_fstring_t)); if (fstat (fd, &st) == -1 || (data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) @@ -617,8 +617,20 @@ lua_cryptobox_signature_load (lua_State *L) lua_pushnil (L); } else { - if (st.st_size == rspamd_cryptobox_signature_bytes ( - RSPAMD_CRYPTOBOX_MODE_25519)) { + if (lua_isstring (L, 2)) { + const gchar *str = lua_tostring (L, 2); + + if (strcmp (str, "nist") == 0 || strcmp (str, "openssl") == 0) { + alg = RSPAMD_CRYPTOBOX_MODE_NIST; + } + else if (strcmp (str, "curve25519") == 0 || strcmp (str, "default") == 0) { + alg = RSPAMD_CRYPTOBOX_MODE_25519; + } + else { + return luaL_error (L, "invalid keypair algorithm: %s", str); + } + } + if (st.st_size > 0) { sig = rspamd_fstring_new_init (data, st.st_size); psig = lua_newuserdata (L, sizeof (rspamd_fstring_t *)); rspamd_lua_setclass (L, "rspamd{cryptobox_signature}", -1); @@ -627,7 +639,7 @@ lua_cryptobox_signature_load (lua_State *L) else { msg_err ("size of %s mismatches: %d while %d is expected", filename, (int)st.st_size, - rspamd_cryptobox_signature_bytes (RSPAMD_CRYPTOBOX_MODE_25519)); + rspamd_cryptobox_signature_bytes (alg)); lua_pushnil (L); } @@ -1289,7 +1301,7 @@ lua_cryptobox_hash_gc (lua_State *L) } /*** - * @function rspamd_cryptobox.verify_memory(pk, sig, data) + * @function rspamd_cryptobox.verify_memory(pk, sig, data, [alg = 'curve25519']) * Check memory using specified cryptobox key and signature * @param {pubkey} pk public key to verify * @param {sig} signature to check @@ -1303,6 +1315,7 @@ lua_cryptobox_verify_memory (lua_State *L) rspamd_fstring_t *signature; struct rspamd_lua_text *t; const gchar *data; + enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519; gsize len; gint ret; @@ -1323,9 +1336,23 @@ lua_cryptobox_verify_memory (lua_State *L) data = luaL_checklstring (L, 3, &len); } + if (lua_isstring (L, 4)) { + const gchar *str = lua_tostring (L, 4); + + if (strcmp (str, "nist") == 0 || strcmp (str, "openssl") == 0) { + alg = RSPAMD_CRYPTOBOX_MODE_NIST; + } + else if (strcmp (str, "curve25519") == 0 || strcmp (str, "default") == 0) { + alg = RSPAMD_CRYPTOBOX_MODE_25519; + } + else { + return luaL_error (L, "invalid algorithm: %s", str); + } + } + if (pk != NULL && signature != NULL && data != NULL) { - ret = rspamd_cryptobox_verify (signature->str, data, len, - rspamd_pubkey_get_pk (pk, NULL), RSPAMD_CRYPTOBOX_MODE_25519); + ret = rspamd_cryptobox_verify (signature->str, signature->len, data, len, + rspamd_pubkey_get_pk (pk, NULL), alg); if (ret) { lua_pushboolean (L, 1); @@ -1342,7 +1369,7 @@ lua_cryptobox_verify_memory (lua_State *L) } /*** - * @function rspamd_cryptobox.verify_file(pk, sig, file) + * @function rspamd_cryptobox.verify_file(pk, sig, file, [alg = 'curve25519']) * Check file using specified cryptobox key and signature * @param {pubkey} pk public key to verify * @param {sig} signature to check @@ -1356,6 +1383,7 @@ lua_cryptobox_verify_file (lua_State *L) struct rspamd_cryptobox_pubkey *pk; rspamd_fstring_t *signature; guchar *map = NULL; + enum rspamd_cryptobox_mode alg = RSPAMD_CRYPTOBOX_MODE_25519; gsize len; gint ret; @@ -1363,11 +1391,26 @@ lua_cryptobox_verify_file (lua_State *L) signature = lua_check_cryptobox_sign (L, 2); fname = luaL_checkstring (L, 3); + if (lua_isstring (L, 4)) { + const gchar *str = lua_tostring (L, 4); + + if (strcmp (str, "nist") == 0 || strcmp (str, "openssl") == 0) { + alg = RSPAMD_CRYPTOBOX_MODE_NIST; + } + else if (strcmp (str, "curve25519") == 0 || strcmp (str, "default") == 0) { + alg = RSPAMD_CRYPTOBOX_MODE_25519; + } + else { + return luaL_error (L, "invalid algorithm: %s", str); + } + } + map = rspamd_file_xmap (fname, PROT_READ, &len, TRUE); if (map != NULL && pk != NULL && signature != NULL) { - ret = rspamd_cryptobox_verify (signature->str, map, len, - rspamd_pubkey_get_pk (pk, NULL), RSPAMD_CRYPTOBOX_MODE_25519); + ret = rspamd_cryptobox_verify (signature->str, signature->len, + map, len, + rspamd_pubkey_get_pk (pk, NULL), alg); if (ret) { lua_pushboolean (L, 1); diff --git a/src/rspamadm/signtool.c b/src/rspamadm/signtool.c index af8d05c96..eae55b8bd 100644 --- a/src/rspamadm/signtool.c +++ b/src/rspamadm/signtool.c @@ -447,7 +447,8 @@ rspamadm_verify_file (const gchar *fname, const guchar *pk) exit (errno); } - ret = rspamd_cryptobox_verify (map_sig, map, st.st_size, pk, mode); + ret = rspamd_cryptobox_verify (map_sig, st_sig.st_size, + map, st.st_size, pk, mode); munmap (map, st.st_size); munmap (map_sig, st_sig.st_size); -- 2.39.5