summaryrefslogtreecommitdiff
path: root/lcrypt/lcrypt_math.c
diff options
context:
space:
mode:
authorNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-08-08 09:23:03 +0200
committerNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-08-08 09:23:03 +0200
commit29e4a0512331a36c1cde22ed26c6ae059fa20757 (patch)
tree09496f029124fe4fc61aa7e014df50349128ced3 /lcrypt/lcrypt_math.c
parent8fd11c9821c23c69da76158c87acdefe2ae9586f (diff)
Adding libtommath, libtomcrypt and lcrypt, mainly for the bignum support.
Diffstat (limited to 'lcrypt/lcrypt_math.c')
-rw-r--r--lcrypt/lcrypt_math.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/lcrypt/lcrypt_math.c b/lcrypt/lcrypt_math.c
new file mode 100644
index 0000000..769a3a4
--- /dev/null
+++ b/lcrypt/lcrypt_math.c
@@ -0,0 +1,401 @@
+#ifdef USE_NCIPHER
+ typedef sbigint lcrypt_bigint;
+#else
+ typedef void* lcrypt_bigint;
+#endif
+
+static lcrypt_bigint* lcrypt_new_bigint(lua_State *L)
+{
+ lcrypt_bigint *bi = lua_newuserdata(L, sizeof(lcrypt_bigint));
+ luaL_getmetatable(L, "LCRYPT_BIGINT");
+ (void)lua_setmetatable(L, -2);
+ #ifdef USE_NCIPHER
+ sbigint_create(bi, NULL, 0);
+ #else
+ *bi = NULL;
+ lcrypt_error(L, ltc_mp.init(bi), NULL);
+ #endif
+ return bi;
+}
+
+static int lcrypt_bigint_add(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_add(bi_a, bi_b, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.add(*bi_a, *bi_b, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_sub(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_sub(bi_a, bi_b, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.sub(*bi_a, *bi_b, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_mul(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_mul(bi_a, bi_b, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.mul(*bi_a, *bi_b, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_div(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_divmod(bi_a, bi_b, bi, NULL) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.mpdiv(*bi_a, *bi_b, *bi, NULL), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_divmod(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_q = lcrypt_new_bigint(L);
+ lcrypt_bigint *bi_r = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_divmod(bi_a, bi_b, bi_q, bi_r) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.mpdiv(*bi_a, *bi_b, *bi_q, *bi_r), NULL);
+ #endif
+ return 2;
+}
+
+static int lcrypt_bigint_mod(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_divmod(bi_a, bi_b, NULL, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.mpdiv(*bi_a, *bi_b, NULL, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_invmod(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_invmod(bi_a, bi_b, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.invmod(*bi_a, *bi_b, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_mulmod(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_c = luaL_checkudata(L, 3, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_mulmod(bi_a, bi_b, bi_c, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.mulmod(*bi_a, *bi_b, *bi_c, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_exptmod(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_c = luaL_checkudata(L, 3, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_exptmod(bi_a, bi_b, bi_c, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.exptmod(*bi_a, *bi_b, *bi_c, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_gcd(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_gcd(bi_a, bi_b, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.gcd(*bi_a, *bi_b, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_lcm(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ if(unlikely(sbigint_lcm(bi_a, bi_b, bi) != 0)) return 0;
+ #else
+ lcrypt_error(L, ltc_mp.lcm(*bi_a, *bi_b, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_unm(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ #ifdef USE_NCIPHER
+ sbigint_copy(bi, bi_a);
+ bi->sign = (bi_a->sign == SBIGINT_POSITIVE) ? SBIGINT_NEGATIVE : SBIGINT_POSITIVE;
+ #else
+ lcrypt_error(L, ltc_mp.neg(*bi_a, *bi), NULL);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_eq(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ #ifdef USE_NCIPHER
+ lua_pushboolean(L, (sbigint_cmp(bi_a, bi_b) == 0) ? 1 : 0);
+ #else
+ lua_pushboolean(L, (ltc_mp.compare(*bi_a, *bi_b) == LTC_MP_EQ) ? 1 : 0);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_lt(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ #ifdef USE_NCIPHER
+ lua_pushboolean(L, (sbigint_cmp(bi_a, bi_b) < 0) ? 1 : 0);
+ #else
+ lua_pushboolean(L, (ltc_mp.compare(*bi_a, *bi_b) == LTC_MP_LT) ? 1 : 0);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_le(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ lcrypt_bigint *bi_b = luaL_checkudata(L, 2, "LCRYPT_BIGINT");
+ #ifdef USE_NCIPHER
+ lua_pushboolean(L, (sbigint_cmp(bi_a, bi_b) <= 0) ? 1 : 0);
+ #else
+ lua_pushboolean(L, (ltc_mp.compare(*bi_a, *bi_b) == LTC_MP_GT) ? 0 : 1);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_tostring(lua_State *L)
+{
+ lcrypt_bigint *bi_a = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ #ifdef USE_NCIPHER
+ unsigned char out[4097];
+ int length = sizeof(out);
+ sbigint_tostring(bi_a, out + 1, &length);
+ if(bi_a->sign == SBIGINT_NEGATIVE || (out[1] & 0x80) == 0x80)
+ {
+ out[0] = bi_a->sign;
+ lua_pushlstring(L, (char*)out, length + 1);
+ }
+ else
+ {
+ lua_pushlstring(L, (char*)out + 1, length);
+ }
+ #else
+ size_t out_length = (size_t)ltc_mp.unsigned_size(*bi_a) + 1;
+ unsigned char *out = lcrypt_malloc(L, out_length);
+ out[0] = (ltc_mp.compare_d(*bi_a, 0) == LTC_MP_LT) ? (unsigned char)0x80 : (unsigned char)0x00;
+ lcrypt_error(L, ltc_mp.unsigned_write(*bi_a, out+1), out);
+ if(out[0] == 0 && out[1] < 0x7f)
+ lua_pushlstring(L, (char*)out+1, out_length-1);
+ else
+ lua_pushlstring(L, (char*)out, out_length);
+ free(out);
+ #endif
+ return 1;
+}
+
+static int lcrypt_bigint_index(lua_State *L)
+{
+ lcrypt_bigint *bi = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ const char *index = luaL_checkstring(L, 2);
+ #ifdef USE_NCIPHER
+ if(strcmp(index, "bits") == 0)
+ {
+ int len = bi->num.nbytes - 1;
+ while(len > 0 && bi->num.bytes[len] == 0) len--;
+ int bits = len * 8;
+ if(bi->num.bytes[len] & 0x80) bits += 8;
+ else if(bi->num.bytes[len] & 0x40) bits += 7;
+ else if(bi->num.bytes[len] & 0x20) bits += 6;
+ else if(bi->num.bytes[len] & 0x10) bits += 5;
+ else if(bi->num.bytes[len] & 0x08) bits += 4;
+ else if(bi->num.bytes[len] & 0x04) bits += 3;
+ else if(bi->num.bytes[len] & 0x02) bits += 2;
+ else bits++;
+ lua_pushinteger(L, bits);
+ return 1;
+ }
+ if(strcmp(index, "isprime") == 0)
+ {
+ sbigint c;
+ int i, prime = 0;
+ if(unlikely(sbigint_is_prime(bi, &c) != 0)) return 0;
+ for(i = 0; i < c.num.nbytes; i++) if(c.num.bytes[i] != 0) { prime = 1; break; }
+ lua_pushboolean(L, prime);
+ return 1;
+ }
+ #else
+ if(strcmp(index, "bits") == 0) { lua_pushinteger(L, ltc_mp.count_bits(*bi)); return 1; }
+ if(strcmp(index, "isprime") == 0)
+ {
+ int ret = LTC_MP_NO;
+ lcrypt_error(L, ltc_mp.isprime(*bi, &ret), NULL);
+ lua_pushboolean(L, (ret == LTC_MP_YES) ? 1 : 0);
+ return 1;
+ }
+ #endif
+ if(strcmp(index, "add") == 0) { lua_pushcfunction(L, lcrypt_bigint_add); return 1; }
+ if(strcmp(index, "sub") == 0) { lua_pushcfunction(L, lcrypt_bigint_sub); return 1; }
+ if(strcmp(index, "mul") == 0) { lua_pushcfunction(L, lcrypt_bigint_mul); return 1; }
+ if(strcmp(index, "div") == 0) { lua_pushcfunction(L, lcrypt_bigint_divmod); return 1; }
+ if(strcmp(index, "mod") == 0) { lua_pushcfunction(L, lcrypt_bigint_mod); return 1; }
+ if(strcmp(index, "gcd") == 0) { lua_pushcfunction(L, lcrypt_bigint_gcd); return 1; }
+ if(strcmp(index, "lcm") == 0) { lua_pushcfunction(L, lcrypt_bigint_lcm); return 1; }
+ if(strcmp(index, "invmod") == 0) { lua_pushcfunction(L, lcrypt_bigint_invmod); return 1; }
+ if(strcmp(index, "mulmod") == 0) { lua_pushcfunction(L, lcrypt_bigint_mulmod); return 1; }
+ if(strcmp(index, "exptmod") == 0) { lua_pushcfunction(L, lcrypt_bigint_exptmod); return 1; }
+ return 0;
+}
+
+static int lcrypt_bigint_gc(lua_State *L)
+{
+ #ifdef USE_NCIPHER
+ (void)luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ #else
+ lcrypt_bigint *bi = luaL_checkudata(L, 1, "LCRYPT_BIGINT");
+ if(likely(*bi != NULL))
+ {
+ ltc_mp.deinit(*bi);
+ *bi = NULL;
+ }
+ #endif
+ return 0;
+}
+
+static int lcrypt_bigint_create(lua_State *L)
+{
+ #ifdef USE_NCIPHER
+ if(lua_isnumber(L, 1) == 1)
+ {
+ long n = luaL_checknumber(L, 1);
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ if(n < 0)
+ {
+ bi->sign = SBIGINT_NEGATIVE;
+ n = -n;
+ }
+ bi->num.nbytes = 0;
+ while(n != 0 || bi->num.nbytes % 4 != 0)
+ {
+ bi->num.bytes[bi->num.nbytes++] = n & 0xff;
+ n >>= 8;
+ }
+ }
+ else
+ {
+ size_t n_length = 0;
+ unsigned char *n = (unsigned char*)luaL_optlstring(L, 1, "", &n_length);
+ lcrypt_bigint *bi = lua_newuserdata(L, sizeof(lcrypt_bigint));
+ luaL_getmetatable(L, "LCRYPT_BIGINT");
+ (void)lua_setmetatable(L, -2);
+ sbigint_create(bi, n, n_length);
+ }
+ #else
+ if(lua_isnumber(L, 1) == 1)
+ {
+ long n = luaL_checknumber(L, 1);
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ if(n < 0)
+ {
+ void *temp;
+ int err = CRYPT_OK;
+ lcrypt_error(L, ltc_mp.init(&temp), NULL);
+ if((err = ltc_mp.set_int(temp, -n)) == CRYPT_OK)
+ {
+ err = ltc_mp.neg(temp, *bi);
+ }
+ ltc_mp.deinit(temp);
+ lcrypt_error(L, err, NULL);
+ }
+ else
+ {
+ lcrypt_error(L, ltc_mp.set_int(*bi, n), NULL);
+ }
+ }
+ else
+ {
+ size_t n_length = 0;
+ unsigned char *n = (unsigned char*)luaL_optlstring(L, 1, "", &n_length);
+ lcrypt_bigint *bi = lcrypt_new_bigint(L);
+ lcrypt_error(L, ltc_mp.unsigned_read(*bi, n, n_length), NULL);
+ }
+ #endif
+ return 1;
+}
+
+static const struct luaL_reg lcrypt_bigint_flib[] =
+{
+ { "__index", lcrypt_bigint_index },
+ { "__add", lcrypt_bigint_add },
+ { "__sub", lcrypt_bigint_sub },
+ { "__mul", lcrypt_bigint_mul },
+ { "__div", lcrypt_bigint_div },
+ { "__mod", lcrypt_bigint_mod },
+ { "__unm", lcrypt_bigint_unm },
+ { "__eq", lcrypt_bigint_eq },
+ { "__lt", lcrypt_bigint_lt },
+ { "__le", lcrypt_bigint_le },
+ { "__tostring", lcrypt_bigint_tostring },
+ { "__gc", lcrypt_bigint_gc },
+ { NULL, NULL }
+};
+
+static void lcrypt_start_math(lua_State *L)
+{
+ (void)luaL_newmetatable(L, "LCRYPT_BIGINT"); (void)luaL_register(L, NULL, lcrypt_bigint_flib); lua_pop(L, 1);
+
+ #ifndef USE_NCIPHER
+ ltc_mp = ltm_desc;
+ #endif
+
+ lua_pushstring(L, "bigint"); lua_pushcfunction(L, lcrypt_bigint_create); lua_settable(L, -3);
+}