aboutsummaryrefslogtreecommitdiffstats
path: root/src/lua/lua_rsa.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2013-06-13 15:47:32 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2013-06-13 15:47:32 +0100
commitb346120d244ee4761bb0b0838ae00264376b97e9 (patch)
tree26c9ecd3051b656e93153f426a9140d6bc543b92 /src/lua/lua_rsa.c
parent9deefe925c11413cb4e37bf6ef7fd13730e7af1d (diff)
downloadrspamd-b346120d244ee4761bb0b0838ae00264376b97e9.tar.gz
rspamd-b346120d244ee4761bb0b0838ae00264376b97e9.zip
Add a simple test of rsa utils in lua.
Support RSA signing in lua_rsa module. Add save function for rsa_signature. Fix test logic for lua modules.
Diffstat (limited to 'src/lua/lua_rsa.c')
-rw-r--r--src/lua/lua_rsa.c360
1 files changed, 325 insertions, 35 deletions
diff --git a/src/lua/lua_rsa.c b/src/lua/lua_rsa.c
index 66b1f9b26..38820e4e2 100644
--- a/src/lua/lua_rsa.c
+++ b/src/lua/lua_rsa.c
@@ -36,30 +36,50 @@
#include <openssl/rsa.h>
#include <openssl/pem.h>
-LUA_FUNCTION_DEF (rsa_key, load);
-LUA_FUNCTION_DEF (rsa_key, create);
-LUA_FUNCTION_DEF (rsa_key, gc);
+LUA_FUNCTION_DEF (rsa_pubkey, load);
+LUA_FUNCTION_DEF (rsa_pubkey, create);
+LUA_FUNCTION_DEF (rsa_pubkey, gc);
+LUA_FUNCTION_DEF (rsa_privkey, load);
+LUA_FUNCTION_DEF (rsa_privkey, create);
+LUA_FUNCTION_DEF (rsa_privkey, gc);
LUA_FUNCTION_DEF (rsa_signature, create);
LUA_FUNCTION_DEF (rsa_signature, load);
+LUA_FUNCTION_DEF (rsa_signature, save);
LUA_FUNCTION_DEF (rsa_signature, gc);
-LUA_FUNCTION_DEF (rsa, check_memory);
-LUA_FUNCTION_DEF (rsa, check_file);
+LUA_FUNCTION_DEF (rsa, verify_memory);
+LUA_FUNCTION_DEF (rsa, verify_file);
+LUA_FUNCTION_DEF (rsa, sign_file);
+LUA_FUNCTION_DEF (rsa, sign_memory);
static const struct luaL_reg rsalib_f[] = {
- LUA_INTERFACE_DEF (rsa, check_memory),
- LUA_INTERFACE_DEF (rsa, check_file),
+ LUA_INTERFACE_DEF (rsa, verify_memory),
+ LUA_INTERFACE_DEF (rsa, verify_file),
+ LUA_INTERFACE_DEF (rsa, sign_memory),
+ LUA_INTERFACE_DEF (rsa, sign_file),
{NULL, NULL}
};
-static const struct luaL_reg rsakeylib_f[] = {
- LUA_INTERFACE_DEF (rsa_key, load),
- LUA_INTERFACE_DEF (rsa_key, create),
+static const struct luaL_reg rsapubkeylib_f[] = {
+ LUA_INTERFACE_DEF (rsa_pubkey, load),
+ LUA_INTERFACE_DEF (rsa_pubkey, create),
{NULL, NULL}
};
-static const struct luaL_reg rsakeylib_m[] = {
+static const struct luaL_reg rsapubkeylib_m[] = {
{"__tostring", lua_class_tostring},
- {"__gc", lua_rsa_key_gc},
+ {"__gc", lua_rsa_pubkey_gc},
+ {NULL, NULL}
+};
+
+static const struct luaL_reg rsaprivkeylib_f[] = {
+ LUA_INTERFACE_DEF (rsa_privkey, load),
+ LUA_INTERFACE_DEF (rsa_privkey, create),
+ {NULL, NULL}
+};
+
+static const struct luaL_reg rsaprivkeylib_m[] = {
+ {"__tostring", lua_class_tostring},
+ {"__gc", lua_rsa_privkey_gc},
{NULL, NULL}
};
@@ -70,17 +90,27 @@ static const struct luaL_reg rsasignlib_f[] = {
};
static const struct luaL_reg rsasignlib_m[] = {
+ LUA_INTERFACE_DEF (rsa_signature, save),
{"__tostring", lua_class_tostring},
{"__gc", lua_rsa_signature_gc},
{NULL, NULL}
};
static RSA *
-lua_check_rsa_key (lua_State * L, int pos)
+lua_check_rsa_pubkey (lua_State * L, int pos)
+{
+ void *ud = luaL_checkudata (L, pos, "rspamd{rsa_pubkey}");
+
+ luaL_argcheck (L, ud != NULL, 1, "'rsa_pubkey' expected");
+ return ud ? *((RSA **)ud) : NULL;
+}
+
+static RSA *
+lua_check_rsa_privkey (lua_State * L, int pos)
{
- void *ud = luaL_checkudata (L, pos, "rspamd{rsa_key}");
+ void *ud = luaL_checkudata (L, pos, "rspamd{rsa_privkey}");
- luaL_argcheck (L, ud != NULL, 1, "'rsa_key' expected");
+ luaL_argcheck (L, ud != NULL, 1, "'rsa_privkey' expected");
return ud ? *((RSA **)ud) : NULL;
}
@@ -94,7 +124,7 @@ lua_check_rsa_sign (lua_State * L, int pos)
}
static gint
-lua_rsa_key_load (lua_State *L)
+lua_rsa_pubkey_load (lua_State *L)
{
RSA *rsa = NULL, **prsa;
const gchar *filename;
@@ -115,7 +145,7 @@ lua_rsa_key_load (lua_State *L)
}
else {
prsa = lua_newuserdata (L, sizeof (RSA *));
- lua_setclass (L, "rspamd{rsa_key}", -1);
+ lua_setclass (L, "rspamd{rsa_pubkey}", -1);
*prsa = rsa;
}
fclose (f);
@@ -128,7 +158,7 @@ lua_rsa_key_load (lua_State *L)
}
static gint
-lua_rsa_key_create (lua_State *L)
+lua_rsa_pubkey_create (lua_State *L)
{
RSA *rsa = NULL, **prsa;
const gchar *buf;
@@ -145,7 +175,7 @@ lua_rsa_key_create (lua_State *L)
}
else {
prsa = lua_newuserdata (L, sizeof (RSA *));
- lua_setclass (L, "rspamd{rsa_key}", -1);
+ lua_setclass (L, "rspamd{rsa_pubkey}", -1);
*prsa = rsa;
}
BIO_free (bp);
@@ -157,9 +187,84 @@ lua_rsa_key_create (lua_State *L)
}
static gint
-lua_rsa_key_gc (lua_State *L)
+lua_rsa_pubkey_gc (lua_State *L)
{
- RSA *rsa = lua_check_rsa_key (L, 1);
+ RSA *rsa = lua_check_rsa_pubkey (L, 1);
+
+ if (rsa != NULL) {
+ RSA_free (rsa);
+ }
+
+ return 0;
+}
+
+static gint
+lua_rsa_privkey_load (lua_State *L)
+{
+ RSA *rsa = NULL, **prsa;
+ const gchar *filename;
+ FILE *f;
+
+ filename = luaL_checkstring (L, 1);
+ if (filename != NULL) {
+ f = fopen (filename, "r");
+ if (f == NULL) {
+ msg_err ("cannot open private key from file: %s, %s", filename, strerror (errno));
+ lua_pushnil (L);
+ }
+ else {
+ if (! PEM_read_RSAPrivateKey (f, &rsa, NULL, NULL)) {
+ msg_err ("cannot open private key from file: %s, %s", filename,
+ ERR_error_string (ERR_get_error (), NULL));
+ lua_pushnil (L);
+ }
+ else {
+ prsa = lua_newuserdata (L, sizeof (RSA *));
+ lua_setclass (L, "rspamd{rsa_privkey}", -1);
+ *prsa = rsa;
+ }
+ fclose (f);
+ }
+ }
+ else {
+ lua_pushnil (L);
+ }
+ return 1;
+}
+
+static gint
+lua_rsa_privkey_create (lua_State *L)
+{
+ RSA *rsa = NULL, **prsa;
+ const gchar *buf;
+ BIO *bp;
+
+ buf = luaL_checkstring (L, 1);
+ if (buf != NULL) {
+ bp = BIO_new_mem_buf ((void *)buf, -1);
+
+ if (! PEM_read_bio_RSAPrivateKey (bp, &rsa, NULL, NULL)) {
+ msg_err ("cannot parse private key: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ lua_pushnil (L);
+ }
+ else {
+ prsa = lua_newuserdata (L, sizeof (RSA *));
+ lua_setclass (L, "rspamd{rsa_privkey}", -1);
+ *prsa = rsa;
+ }
+ BIO_free (bp);
+ }
+ else {
+ lua_pushnil (L);
+ }
+ return 1;
+}
+
+static gint
+lua_rsa_privkey_gc (lua_State *L)
+{
+ RSA *rsa = lua_check_rsa_privkey (L, 1);
if (rsa != NULL) {
RSA_free (rsa);
@@ -211,6 +316,53 @@ lua_rsa_signature_load (lua_State *L)
}
static gint
+lua_rsa_signature_save (lua_State *L)
+{
+ f_str_t *sig;
+ gint fd, flags;
+ const gchar *filename;
+ gboolean forced = FALSE, res = TRUE;
+
+ sig = lua_check_rsa_sign (L, 1);
+ filename = luaL_checkstring (L, 2);
+ if (lua_gettop (L) > 2) {
+ forced = lua_toboolean (L, 3);
+ }
+
+ if (sig != NULL && filename != NULL) {
+ flags = O_WRONLY | O_CREAT;
+ if (forced) {
+ flags |= O_TRUNC;
+ }
+ else {
+ flags |= O_EXCL;
+ }
+ fd = open (filename, flags, 00644);
+ if (fd == -1) {
+ msg_err ("cannot create a signature file: %s, %s", filename, strerror (errno));
+ lua_pushboolean (L, FALSE);
+ }
+ else {
+ while (write (fd, sig->begin, sig->len) == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ msg_err ("cannot write to a signature file: %s, %s", filename, strerror (errno));
+ res = FALSE;
+ break;
+ }
+ lua_pushboolean (L, res);
+ close (fd);
+ }
+ }
+ else {
+ lua_pushboolean (L, FALSE);
+ }
+
+ return 1;
+}
+
+static gint
lua_rsa_signature_create (lua_State *L)
{
f_str_t *sig, **psig;
@@ -250,14 +402,14 @@ lua_rsa_signature_gc (lua_State *L)
* Check memory using specified rsa key and signature
*
* arguments:
- * (rsa_key, rsa_signature, string)
+ * (rsa_pubkey, rsa_signature, string)
*
* returns:
* true - if string match rsa signature
* false - otherwise
*/
static gint
-lua_rsa_check_memory (lua_State *L)
+lua_rsa_verify_memory (lua_State *L)
{
RSA *rsa;
f_str_t *signature;
@@ -265,19 +417,23 @@ lua_rsa_check_memory (lua_State *L)
gchar *data_sig;
gint ret;
- rsa = lua_check_rsa_key (L, 1);
+ rsa = lua_check_rsa_pubkey (L, 1);
signature = lua_check_rsa_sign (L, 2);
data = luaL_checkstring (L, 3);
if (rsa != NULL && signature != NULL && data != NULL) {
data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, -1);
- ret = RSA_verify (NID_sha1, signature->begin, signature->len, data_sig, strlen (data_sig), rsa);
+ ret = RSA_verify (NID_sha1, data_sig, strlen (data_sig),
+ signature->begin, signature->len, rsa);
if (ret == 0) {
+ msg_info ("cannot check rsa signature for data: %s",
+ ERR_error_string (ERR_get_error (), NULL));
lua_pushboolean (L, FALSE);
}
else {
lua_pushboolean (L, TRUE);
}
+ g_free (data_sig);
}
else {
lua_pushnil (L);
@@ -290,14 +446,14 @@ lua_rsa_check_memory (lua_State *L)
* Check memory using specified rsa key and signature
*
* arguments:
- * (rsa_key, rsa_signature, string)
+ * (rsa_pubkey, rsa_signature, string)
*
* returns:
* true - if string match rsa signature
* false - otherwise
*/
static gint
-lua_rsa_check_file (lua_State *L)
+lua_rsa_verify_file (lua_State *L)
{
RSA *rsa;
f_str_t *signature;
@@ -306,11 +462,11 @@ lua_rsa_check_file (lua_State *L)
gint ret, fd;
struct stat st;
- rsa = lua_check_rsa_key (L, 1);
+ rsa = lua_check_rsa_pubkey (L, 1);
signature = lua_check_rsa_sign (L, 2);
filename = luaL_checkstring (L, 3);
- if (rsa != NULL && signature != NULL && data != NULL) {
+ if (rsa != NULL && signature != NULL && filename != NULL) {
fd = open (filename, O_RDONLY);
if (fd == -1) {
msg_err ("cannot open file %s: %s", filename, strerror (errno));
@@ -324,14 +480,136 @@ lua_rsa_check_file (lua_State *L)
}
else {
data_sig = g_compute_checksum_for_data (G_CHECKSUM_SHA256, data, st.st_size);
- ret = RSA_verify (NID_sha1, signature->begin, signature->len,
- data_sig, strlen (data_sig), rsa);
+ ret = RSA_verify (NID_sha1, data_sig, strlen (data_sig),
+ signature->begin, signature->len, rsa);
if (ret == 0) {
+ msg_info ("cannot check rsa signature for file: %s, %s",
+ filename, ERR_error_string (ERR_get_error (), NULL));
lua_pushboolean (L, FALSE);
}
else {
lua_pushboolean (L, TRUE);
}
+ g_free (data_sig);
+ munmap (data, st.st_size);
+ }
+ close (fd);
+ }
+ }
+ else {
+ lua_pushnil (L);
+ }
+
+ return 1;
+}
+
+/**
+ * Sign memory using specified rsa key and signature
+ *
+ * arguments:
+ * (rsa_privkey, string)
+ *
+ * returns:
+ * rspamd_signature object
+ * nil - otherwise
+ */
+static gint
+lua_rsa_sign_memory (lua_State *L)
+{
+ RSA *rsa;
+ f_str_t *signature, **psig;
+ const gchar *data;
+ gchar *data_sig;
+ gint ret;
+
+ rsa = lua_check_rsa_privkey (L, 1);
+ data = luaL_checkstring (L, 2);
+
+ if (rsa != NULL && data != NULL) {
+ signature = g_malloc (sizeof (f_str_t));
+ signature->len = RSA_size (rsa);
+ signature->size = signature->len;
+ signature->begin = g_malloc (signature->len);
+ data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, -1);
+ ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig),
+ signature->begin, (guint *)&signature->len, rsa);
+ if (ret == 0) {
+ msg_info ("cannot make a signature for data: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ lua_pushnil (L);
+ g_free (signature->begin);
+ g_free (signature);
+ }
+ else {
+ psig = lua_newuserdata (L, sizeof (f_str_t *));
+ lua_setclass (L, "rspamd{rsa_signature}", -1);
+ *psig = signature;
+ }
+ g_free (data_sig);
+ }
+ else {
+ lua_pushnil (L);
+ }
+
+ return 1;
+}
+
+/**
+ * Sign file using specified rsa key and signature
+ *
+ * arguments:
+ * (rsa_privkey, rsa_signature, string)
+ *
+ * returns:
+ * true - if string match rsa signature
+ * false - otherwise
+ */
+static gint
+lua_rsa_sign_file (lua_State *L)
+{
+ RSA *rsa;
+ f_str_t *signature, **psig;
+ const gchar *filename;
+ gchar *data = NULL, *data_sig;
+ gint ret, fd;
+ struct stat st;
+
+ rsa = lua_check_rsa_privkey (L, 1);
+ filename = luaL_checkstring (L, 2);
+
+ if (rsa != NULL && filename != NULL) {
+ fd = open (filename, O_RDONLY);
+ if (fd == -1) {
+ msg_err ("cannot open file %s: %s", filename, strerror (errno));
+ lua_pushnil (L);
+ }
+ else {
+ if (fstat (fd, &st) == -1 ||
+ (data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+ msg_err ("cannot mmap file %s: %s", filename, strerror (errno));
+ lua_pushnil (L);
+ }
+ else {
+ signature = g_malloc (sizeof (f_str_t));
+ signature->len = RSA_size (rsa);
+ signature->size = signature->len;
+ signature->begin = g_malloc (signature->len);
+ data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, st.st_size);
+ ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig),
+ signature->begin, (guint *)&signature->len, rsa);
+ if (ret == 0) {
+ msg_info ("cannot make a signature for data: %s",
+ ERR_error_string (ERR_get_error (), NULL));
+ lua_pushnil (L);
+ g_free (signature->begin);
+ g_free (signature);
+ }
+ else {
+ psig = lua_newuserdata (L, sizeof (f_str_t *));
+ lua_setclass (L, "rspamd{rsa_signature}", -1);
+ *psig = signature;
+ }
+ g_free (data_sig);
munmap (data, st.st_size);
}
close (fd);
@@ -347,17 +625,29 @@ lua_rsa_check_file (lua_State *L)
gint
luaopen_rsa (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{rsa_key}");
+ luaL_newmetatable (L, "rspamd{rsa_pubkey}");
+ lua_pushstring (L, "__index");
+ lua_pushvalue (L, -2);
+ lua_settable (L, -3);
+
+ lua_pushstring (L, "class");
+ lua_pushstring (L, "rspamd{rsa_pubkey}");
+ lua_rawset (L, -3);
+
+ luaL_register (L, NULL, rsapubkeylib_m);
+ luaL_register (L, "rsa_pubkey", rsapubkeylib_f);
+
+ luaL_newmetatable (L, "rspamd{rsa_privkey}");
lua_pushstring (L, "__index");
lua_pushvalue (L, -2);
lua_settable (L, -3);
lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_key}");
+ lua_pushstring (L, "rspamd{rsa_privkey}");
lua_rawset (L, -3);
- luaL_register (L, NULL, rsakeylib_m);
- luaL_register (L, "rsa_key", rsakeylib_f);
+ luaL_register (L, NULL, rsaprivkeylib_m);
+ luaL_register (L, "rsa_privkey", rsaprivkeylib_f);
luaL_newmetatable (L, "rspamd{rsa_signature}");
lua_pushstring (L, "__index");