From 29e4a0512331a36c1cde22ed26c6ae059fa20757 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 8 Aug 2013 09:23:03 +0200 Subject: Adding libtommath, libtomcrypt and lcrypt, mainly for the bignum support. --- lcrypt/lcrypt_ciphers.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 lcrypt/lcrypt_ciphers.c (limited to 'lcrypt/lcrypt_ciphers.c') diff --git a/lcrypt/lcrypt_ciphers.c b/lcrypt/lcrypt_ciphers.c new file mode 100644 index 0000000..dc8c47b --- /dev/null +++ b/lcrypt/lcrypt_ciphers.c @@ -0,0 +1,403 @@ +static void lcrypt_ivlength(lua_State *L, int cipher, size_t *iv_length) +{ + if(unlikely(*iv_length < (size_t)cipher_descriptor[cipher].block_length)) + { + lua_pushstring(L, "IV wrong length"); + (void)lua_error(L); + } + *iv_length = (size_t)cipher_descriptor[cipher].block_length; +} + +#define LCRYPT_CIPHER_XXX_START(NAME, name) \ +static int lcrypt_cipher_ ## name (lua_State *L) \ +{ \ + symmetric_ ## NAME *skey; \ + int err = CRYPT_OK, *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); \ + size_t key_length, iv_length; \ + const unsigned char *key = (const unsigned char *)luaL_checklstring(L, 2, &key_length); \ + const unsigned char *iv = (const unsigned char *)luaL_checklstring(L, 3, &iv_length); \ + lcrypt_ivlength(L, *cipher, &iv_length); \ + skey = lua_newuserdata(L, sizeof(symmetric_ ## NAME)); \ + luaL_getmetatable(L, "LCRYPT_CIPHER_" #NAME); \ + (void)lua_setmetatable(L, -2); \ + memset(skey, 0, sizeof(symmetric_ ## NAME)); \ + if(unlikely((err = name ## _start(*cipher, iv, key, (int)key_length, 0, skey)) != CRYPT_OK)) \ + { \ + skey->cipher = -1; \ + lcrypt_error(L, err, NULL); \ + } \ + return 1; \ +} + +#define LCRYPT_CIPHER_XXX_INDEX(NAME, _name) \ +static int lcrypt_cipher_ ## _name ## _index(lua_State *L) \ +{ \ + symmetric_ ## NAME *skey = luaL_checkudata(L, 1, "LCRYPT_CIPHER_" #NAME); \ + if(unlikely(skey->cipher < 0)) return 0; \ + const char *index = luaL_checkstring(L, 2); \ + if(strcmp(index, "type") == 0) { lua_pushstring(L, "LCRYPT_CIPHER_" #NAME); return 1; } \ + if(strcmp(index, "iv") == 0) \ + { \ + unsigned char iv[MAXBLOCKSIZE]; \ + unsigned long length = MAXBLOCKSIZE; \ + lcrypt_error(L, _name ## _getiv(iv, &length, skey), NULL); \ + lua_pushlstring(L, (char*)iv, (size_t)length); \ + return 1; \ + } \ + if(strcmp(index, "block_size") == 0) \ + { \ + lua_pushinteger(L, cipher_descriptor[skey->cipher].block_length); \ + return 1; \ + } \ + if(strcmp(index, "encrypt") == 0) \ + { \ + lua_pushcfunction(L, lcrypt_cipher_ ## _name ## _encrypt); \ + return 1; \ + } \ + if(strcmp(index, "decrypt") == 0) \ + { \ + lua_pushcfunction(L, lcrypt_cipher_ ## _name ## _decrypt); \ + return 1; \ + } \ + if(strcmp(index, "cipher_name") == 0) \ + { \ + lua_pushstring(L, cipher_descriptor[skey->cipher].name); \ + return 1; \ + } \ + if(strcmp(index, "mode_name") == 0) \ + { \ + lua_pushstring(L, #_name); \ + return 1; \ + } \ + return 0; \ +} + +#define LCRYPT_CIPHER_XXX_NEWINDEX(NAME, name) \ +static int lcrypt_cipher_ ## name ## _newindex(lua_State *L) \ +{ \ + symmetric_ ## NAME *skey = luaL_checkudata(L, 1, "LCRYPT_CIPHER_" #NAME); \ + size_t v_length = 0; \ + const char *index = luaL_checkstring(L, 2); \ + const unsigned char *v = (const unsigned char *)luaL_checklstring(L, 3, &v_length); \ + if(unlikely(skey->cipher < 0)) return 0; \ + if(strcmp(index, "iv") == 0) \ + { \ + lcrypt_error(L, name ## _setiv(v, v_length, skey), NULL); \ + } \ + return 0; \ +} + +#define LCRYPT_CIPHER_XXX_GC(NAME, name) \ +static int lcrypt_cipher_ ## name ## _gc(lua_State *L) \ +{ \ + symmetric_ ## NAME *skey = luaL_checkudata(L, 1, "LCRYPT_CIPHER_" #NAME); \ + if(likely(skey->cipher != -1)) lcrypt_error(L, name ## _done(skey), NULL); \ + return 0; \ +} + +#define LCRYPT_CIPHER_XXX_ENCRYPT(NAME, name) \ +static int lcrypt_cipher_ ## name ## _encrypt(lua_State *L) \ +{ \ + symmetric_ ## NAME *skey = luaL_checkudata(L, 1, "LCRYPT_CIPHER_" #NAME); \ + if(likely(skey->cipher >= 0)) \ + { \ + size_t in_length = 0; \ + const unsigned char *in = (const unsigned char *)luaL_checklstring(L, 2, &in_length); \ + int i, block_length = cipher_descriptor[skey->cipher].block_length; \ + int padding_length = in_length + block_length - in_length % block_length; \ +printf("in_length = %d, padding_length = %d\n", in_length, padding_length); \ + unsigned char *out = lcrypt_malloc(L, 2 * (in_length + padding_length)); \ + memcpy(out + in_length + padding_length, in, in_length); \ + memset(out + in_length + padding_length + in_length, padding_length, padding_length); \ + in = out + in_length + padding_length; \ + for(i = 0; i < in_length + padding_length; i += block_length) \ + { \ + lcrypt_error(L, name ## _encrypt(in + i, out + i, block_length, skey), out); \ + } \ + lua_pushlstring(L, (char*)out, in_length + padding_length); \ + free(out); \ + return 1; \ + } \ + return 0; \ +} + +#define LCRYPT_CIPHER_XXX_DECRYPT(NAME, name) \ +static int lcrypt_cipher_ ## name ## _decrypt(lua_State *L) \ +{ \ + symmetric_ ## NAME *skey = luaL_checkudata(L, 1, "LCRYPT_CIPHER_" #NAME); \ + if(likely(skey->cipher >= 0)) \ + { \ + size_t in_length = 0; \ + const unsigned char *in = (const unsigned char *)luaL_checklstring(L, 2, &in_length); \ + unsigned char *out = lcrypt_malloc(L, in_length); \ + lcrypt_error(L, name ## _decrypt(in, out, in_length, skey), out); \ + in_length -= out[in_length - 1]; \ + lua_pushlstring(L, (char*)out, in_length); \ + free(out); \ + return 1; \ + } \ + return 0; \ +} + +#define LCRYPT_CIPHER_XXX(NAME, name) \ + LCRYPT_CIPHER_XXX_START(NAME, name) \ + LCRYPT_CIPHER_XXX_NEWINDEX(NAME, name) \ + LCRYPT_CIPHER_XXX_GC(NAME, name) \ + LCRYPT_CIPHER_XXX_ENCRYPT(NAME, name) \ + LCRYPT_CIPHER_XXX_DECRYPT(NAME, name) \ + LCRYPT_CIPHER_XXX_INDEX(NAME, name) + +static int lcrypt_cipher_ecb(lua_State *L) +{ + int err = CRYPT_OK, *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); + size_t key_length; + const unsigned char *key = (const unsigned char *)luaL_checklstring(L, 2, &key_length); + symmetric_ECB *skey = lua_newuserdata(L, sizeof(symmetric_ECB)); + memset(skey, 0, sizeof(symmetric_ECB)); + luaL_getmetatable(L, "LCRYPT_CIPHER_ECB"); + (void)lua_setmetatable(L, -2); + if(unlikely((err = ecb_start(*cipher, key, (int)key_length, 0, skey)) != CRYPT_OK)) + { + skey->cipher = -1; + lcrypt_error(L, err, NULL); + } + return 1; +} + +LCRYPT_CIPHER_XXX_ENCRYPT(ECB, ecb) +LCRYPT_CIPHER_XXX_DECRYPT(ECB, ecb) + +static int lcrypt_cipher_ecb_index(lua_State *L) +{ + symmetric_ECB *skey = luaL_checkudata(L, 1, "LCRYPT_CIPHER_ECB"); + const char *index = luaL_checkstring(L, 2); + if(unlikely(skey->cipher < 0)) return 0; + if(strcmp(index, "type") == 0) { lua_pushstring(L, "LCRYPT_CIPHER_ECB"); return 1; } + if(strcmp(index, "encrypt") == 0) + { + lua_pushcfunction(L, lcrypt_cipher_ecb_encrypt); + return 1; + } + if(strcmp(index, "decrypt") == 0) + { + lua_pushcfunction(L, lcrypt_cipher_ecb_decrypt); + return 1; + } + if(strcmp(index, "cipher_name") == 0) + { + lua_pushstring(L, cipher_descriptor[skey->cipher].name); + return 1; + } + if(strcmp(index, "mode_name") == 0) + { + lua_pushstring(L, "ecb"); + return 1; + } + return 0; +} + +static int lcrypt_cipher_ecb_newindex(lua_State *L) +{ + luaL_checkudata(L, 1, "LCRYPT_CIPHER_ECB"); + return 0; +} + +LCRYPT_CIPHER_XXX_GC(ECB, ecb) + +static int lcrypt_cipher_ctr(lua_State *L) +{ + symmetric_CTR *skey; + int err = CRYPT_OK, *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); + size_t key_length, iv_length; + const unsigned char *key = (const unsigned char *)luaL_checklstring(L, 2, &key_length); + const unsigned char *iv = (const unsigned char *)luaL_checklstring(L, 3, &iv_length); + const char *endian = luaL_optstring(L, 4, "big"); + lcrypt_ivlength(L, *cipher, &iv_length); + skey = lua_newuserdata(L, sizeof(symmetric_CTR)); + memset(skey, 0, sizeof(symmetric_CTR)); + luaL_getmetatable(L, "LCRYPT_CIPHER_CTR"); + (void)lua_setmetatable(L, -2); + if(strcmp(endian, "big") == 0) + { + err = ctr_start(*cipher, iv, key, (int)key_length, 0, CTR_COUNTER_BIG_ENDIAN, skey); + } + else if(strcmp(endian, "little") == 0) + { + err = ctr_start(*cipher, iv, key, (int)key_length, 0, CTR_COUNTER_LITTLE_ENDIAN, skey); + } + else + { + lua_pushstring(L, "Unknown endian"); + (void)lua_error(L); + } + if(unlikely(err != CRYPT_OK)) + { + skey->cipher = -1; + lcrypt_error(L, err, NULL); + } + return 1; +} + +LCRYPT_CIPHER_XXX_ENCRYPT(CTR, ctr) +LCRYPT_CIPHER_XXX_DECRYPT(CTR, ctr) +LCRYPT_CIPHER_XXX_INDEX(CTR, ctr) +LCRYPT_CIPHER_XXX_NEWINDEX(CTR, ctr) +LCRYPT_CIPHER_XXX_GC(CTR, ctr) + +LCRYPT_CIPHER_XXX(CBC, cbc) +LCRYPT_CIPHER_XXX(CFB, cfb) +LCRYPT_CIPHER_XXX(OFB, ofb) + +static int lcrypt_cipher_lrw(lua_State *L) +{ + symmetric_LRW *skey; + int err = CRYPT_OK, *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); + size_t key_length, iv_length, tweak_length; + const unsigned char *key = (const unsigned char *)luaL_checklstring(L, 2, &key_length); + const unsigned char *iv = (const unsigned char *)luaL_checklstring(L, 3, &iv_length); + const unsigned char *tweak = (const unsigned char *)luaL_checklstring(L, 4, &tweak_length); + if(unlikely(tweak_length != 16)) + { + lua_pushstring(L, "Tweak must be 16 characters"); + (void)lua_error(L); + } + lcrypt_ivlength(L, *cipher, &iv_length); + skey = lua_newuserdata(L, sizeof(symmetric_LRW)); + memset(skey, 0, sizeof(symmetric_LRW)); + luaL_getmetatable(L, "LCRYPT_CIPHER_LRW"); + (void)lua_setmetatable(L, -2); + if(unlikely((err = lrw_start(*cipher, iv, key, (int)key_length, tweak, 0, skey)) != CRYPT_OK)) + { + skey->cipher = -1; + lcrypt_error(L, err, NULL); + } + return 1; +} + +LCRYPT_CIPHER_XXX_ENCRYPT(LRW, lrw) +LCRYPT_CIPHER_XXX_DECRYPT(LRW, lrw) +LCRYPT_CIPHER_XXX_INDEX(LRW, lrw) +LCRYPT_CIPHER_XXX_NEWINDEX(LRW, lrw) +LCRYPT_CIPHER_XXX_GC(LRW, lrw) + +static int lcrypt_cipher_f8(lua_State *L) +{ + symmetric_F8 *skey; + int err = CRYPT_OK, *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); + size_t key_length, iv_length, salt_length; + const unsigned char *key = (const unsigned char *)luaL_checklstring(L, 2, &key_length); + const unsigned char *iv = (const unsigned char *)luaL_checklstring(L, 3, &iv_length); + const unsigned char *salt = (const unsigned char *)luaL_checklstring(L, 4, &salt_length); + lcrypt_ivlength(L, *cipher, &iv_length); + skey = lua_newuserdata(L, sizeof(symmetric_F8)); + memset(skey, 0, sizeof(symmetric_F8)); + luaL_getmetatable(L, "LCRYPT_CIPHER_F8"); + (void)lua_setmetatable(L, -2); + if(unlikely((err = f8_start(*cipher, iv, key, (int)key_length, salt, salt_length, 0, skey)) != CRYPT_OK)) + { + skey->cipher = -1; + lcrypt_error(L, err, NULL); + } + return 1; +} + +LCRYPT_CIPHER_XXX_ENCRYPT(F8, f8) +LCRYPT_CIPHER_XXX_DECRYPT(F8, f8) +LCRYPT_CIPHER_XXX_INDEX(F8, f8) +LCRYPT_CIPHER_XXX_NEWINDEX(F8, f8) +LCRYPT_CIPHER_XXX_GC(F8, f8) + +#undef LCRYPT_CIPHER_XXX +#undef LCRYPT_CIPHER_XXX_START +#undef LCRYPT_CIPHER_XXX_INDEX +#undef LCRYPT_CIPHER_XXX_NEWINDEX +#undef LCRYPT_CIPHER_XXX_GC + + +static int lcrypt_cipher_key_size(lua_State *L) +{ + int *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); + int keysize = luaL_checkint(L, 2); + lcrypt_error(L, cipher_descriptor[*cipher].keysize(&keysize), NULL); + lua_pushinteger(L, keysize); + return 1; +} + +static int lcrypt_cipher_index(lua_State *L) +{ + int *cipher = luaL_checkudata(L, 1, "LCRYPT_CIPHER"); + const char *index = luaL_checkstring(L, 2); + + #define RETURN_BLOCK_MODE(name) { if(strcmp(index, #name) == 0) { lua_pushcfunction(L, lcrypt_cipher_ ## name); return 1; } } + RETURN_BLOCK_MODE(ecb); RETURN_BLOCK_MODE(cbc); RETURN_BLOCK_MODE(ctr); RETURN_BLOCK_MODE(cfb); + RETURN_BLOCK_MODE(ofb); RETURN_BLOCK_MODE(f8); + if(cipher_descriptor[*cipher].block_length == 16) RETURN_BLOCK_MODE(lrw); + #undef RETURN_BLOCK_MODE + + if(strcmp(index, "type") == 0) { lua_pushstring(L, "LCRYPT_CIPHER"); return 1; } + if(strcmp(index, "name") == 0) { lua_pushstring(L, cipher_descriptor[*cipher].name); return 1; } + if(strcmp(index, "min_key_length") == 0) { lua_pushinteger(L, cipher_descriptor[*cipher].min_key_length); return 1; } + if(strcmp(index, "max_key_length") == 0) { lua_pushinteger(L, cipher_descriptor[*cipher].max_key_length); return 1; } + if(strcmp(index, "block_length") == 0) { lua_pushinteger(L, cipher_descriptor[*cipher].block_length); return 1; } + if(strcmp(index, "key_size") == 0) { lua_pushcfunction(L, lcrypt_cipher_key_size); return 1; } + if(strcmp(index, "modes") == 0) + { + lua_newtable(L); + #define ADD_MODE(i, name) { lua_pushinteger(L, i); lua_pushstring(L, #name); lua_settable(L, -3); } + ADD_MODE(1, ecb); ADD_MODE(2, cbc); ADD_MODE(3, ctr); ADD_MODE(4, cfb); + ADD_MODE(5, ofb); ADD_MODE(6, f8); + if(cipher_descriptor[*cipher].block_length == 16) ADD_MODE(7, lrw); + #undef ADD_MODE + return 1; + } + + return 0; +} + +static const struct luaL_reg lcrypt_cipher_flib[] = +{ + { "__index", lcrypt_cipher_index }, + { NULL, NULL } +}; + +#define CIPHER_MODE_FLIB(mode) \ +static const struct luaL_reg lcrypt_cipher_ ## mode ## _flib[] = \ +{ \ + { "__index", lcrypt_cipher_ ## mode ## _index }, \ + { "__newindex", lcrypt_cipher_ ## mode ## _newindex }, \ + { "__gc", lcrypt_cipher_ ## mode ## _gc }, \ + { NULL, NULL } \ +}; +CIPHER_MODE_FLIB(ecb); CIPHER_MODE_FLIB(cbc); CIPHER_MODE_FLIB(ctr); +CIPHER_MODE_FLIB(cfb); CIPHER_MODE_FLIB(ofb); CIPHER_MODE_FLIB(f8); +CIPHER_MODE_FLIB(lrw); +#undef CIPHER_MODE_FLIB + +static void lcrypt_start_ciphers(lua_State *L) +{ + (void)luaL_newmetatable(L, "LCRYPT_CIPHER"); (void)luaL_register(L, NULL, lcrypt_cipher_flib); lua_pop(L, 1); + lua_pushstring(L, "ciphers"); + lua_newtable(L); + #define ADD_CIPHER(L,name) \ + { \ + lua_pushstring(L, #name); \ + int *cipher_index = lua_newuserdata(L, sizeof(int)); \ + luaL_getmetatable(L, "LCRYPT_CIPHER"); \ + (void)lua_setmetatable(L, -2); \ + *cipher_index = register_cipher(&name ## _desc); \ + lua_settable(L, -3); \ + } + ADD_CIPHER(L, blowfish); ADD_CIPHER(L, xtea); ADD_CIPHER(L, rc2); ADD_CIPHER(L, rc5); + ADD_CIPHER(L, rc6); ADD_CIPHER(L, saferp); ADD_CIPHER(L, aes); ADD_CIPHER(L, twofish); + ADD_CIPHER(L, des); ADD_CIPHER(L, des3); ADD_CIPHER(L, cast5); ADD_CIPHER(L, noekeon); + ADD_CIPHER(L, skipjack); ADD_CIPHER(L, anubis); ADD_CIPHER(L, khazad); ADD_CIPHER(L, kseed); + ADD_CIPHER(L, kasumi); + #undef ADD_CIPHER + lua_settable(L, -3); + + #define NEW_MODE_TYPE(NAME, name) (void)luaL_newmetatable(L, "LCRYPT_CIPHER_" #NAME); (void)luaL_register(L, NULL, lcrypt_cipher_ ## name ## _flib); lua_pop(L, 1); + NEW_MODE_TYPE(ECB, ecb); NEW_MODE_TYPE(CBC, cbc); NEW_MODE_TYPE(CTR, ctr); + NEW_MODE_TYPE(CFB, cfb); NEW_MODE_TYPE(OFB, ofb); NEW_MODE_TYPE(F8, f8); + NEW_MODE_TYPE(LRW, lrw); + #undef NEW_MODE_TYPE +} -- cgit v1.2.3