Browse Source

Adding karatsuba multiplication.

Michele Orrù 7 years ago
parent
commit
b444c6b360
9 changed files with 136 additions and 35 deletions
  1. 4 3
      src/Makefile.am
  2. 0 2
      src/ddlog.c
  3. 1 1
      src/exp_bench.c
  4. 20 0
      src/fbase.c
  5. 1 13
      src/fbase.h
  6. 44 0
      src/group.c
  7. 13 0
      src/group.h
  8. 38 0
      src/group_test.c
  9. 15 16
      src/rms.c

+ 4 - 3
src/Makefile.am

@@ -1,5 +1,5 @@
 bin_PROGRAMS = rms ddlog_bench exp_bench
-#check_programs = test_ssl1
+check_PROGRAMS = group_test
 
 DDLOG = ddlog.c ddlog.h
 ELGAMAL = elgamal.c elgamal.h
@@ -8,9 +8,10 @@ FBASE = fbase.c fbase.h
 GROUP = group.c group.h
 HSS = hss.c hss.h
 TIMEIT = timeit.h
-#TESTS = $(check_programs)
+TESTS = $(check_PROGRAMS)
+
+group_test_SOURCES = group_test.c $(GROUP) $(ENTROPY)
 
-#test_ssl1_SOURCES = test_ssl1.c
 rms_SOURCES = rms.c $(DDLOG) $(ELGAMAL) $(ENTROPY) $(GROUP) $(FBASE) $(HSS) $(TIMEIT)
 ddlog_bench_SOURCES = ddlog_bench.c $(DDLOG) $(ENTROPY) $(GROUP) $(TIMEIT)
 exp_bench_SOURCES = exp_bench.c $(ENTROPY) $(GROUP) $(FBASE) $(TIMEIT)

+ 0 - 2
src/ddlog.c

@@ -8,8 +8,6 @@
 #include "group.h"
 #include "hss.h"
 
-typedef __uint128_t uint128_t;
-
 uint32_t lookup[256];
 uint32_t offset[256];
 

+ 1 - 1
src/exp_bench.c

@@ -33,7 +33,7 @@ int main()
   fb_set(pbase, base);
 
   INIT_TIMEIT(CLOCK_PROCESS_CPUTIME_ID);
-  for (int i = 0; i < (int) 1e3; i++) {
+  for (int i = 0; i < (int) 1e6; i++) {
     getrandom(&exp, 4, GRND_NONBLOCK);
     //exp =0xffff;
 

+ 20 - 0
src/fbase.c

@@ -27,6 +27,9 @@ void fb_set_small(fbase_t pb, const mpz_t n)
     for (size_t i = 0; i <= 0xFF; i++) {
       uint64_t e =  (0x01 <<  8*j) * i;
       powmp_ui(pb[j][i], n, e);
+      _mpz_realloc(pb[j][i], 24);
+      SIZ(pb[j][i]) = 24;
+
     }
   }
   mpz_clear(e);
@@ -37,6 +40,8 @@ void fb_copy(fbase_t dst, fbase_t source)
   for (size_t j = 0; j < FB_FRAMES; j++) {
     for (size_t i = 0; i <= 0xFF; i++) {
       mpz_set(dst[j][i], source[j][i]);
+      _mpz_realloc(dst[j][i], 24);
+      SIZ(dst[j][i]) = 24;
     }
   }
 }
@@ -67,3 +72,18 @@ void fb_clear(fbase_t pb)
   }
   free(pb);
 }
+
+
+void __attribute__((optimize("unroll-loops")))
+fb_powmp_ui(mpz_t rop, fbase_t pb, const uint64_t exp)
+{
+  const uint8_t *e = (uint8_t *) &exp;
+
+  mpz_mul_modp(rop, pb[0][e[0]], pb[1][e[1]]);
+  for (size_t j = 2; j < FB_FRAMES; j++) {
+    const size_t exp = e[j];
+    if (exp != 0) {
+      mpz_mul_modp(rop, rop,  pb[j][exp]);
+    }
+  }
+}

+ 1 - 13
src/fbase.h

@@ -10,19 +10,7 @@ typedef mpz_t fbase_unit[256];
 typedef fbase_unit   fbase_t[FB_FRAMES];
 typedef fbase_unit  *fbase_ptr;
 
-static inline void __attribute__((optimize("unroll-loops")))
-fb_powmp_ui(mpz_t rop, fbase_t pb, const uint64_t exp)
-{
-  const uint8_t *e = (uint8_t *) &exp;
-
-  mpz_mul_modp(rop, pb[0][e[0]], pb[1][e[1]]);
-  for (size_t j = 2; j < FB_FRAMES; j++) {
-    const size_t exp = e[j];
-    if (exp != 0) {
-      mpz_mul_modp(rop, rop,  pb[j][exp]);
-    }
-  }
-}
+void fb_powmp_ui(mpz_t rop, fbase_t pb, const uint64_t exp);
 
 fbase_ptr fb_init();
 void fb_set(fbase_t pb, const mpz_t n);

+ 44 - 0
src/group.c

@@ -42,3 +42,47 @@ void powmp_ui(mpz_t x, const mpz_t base, uint64_t exp)
   mpz_mul_modp(x, x, y);
   mpz_clear(y);
 }
+
+void mul_modp(mpz_t rop, mpz_t op1, mpz_t op2)
+{
+  mp_limb_t z2[24+2];
+  mp_limb_t z0[24+2];
+  mp_limb_t z1[24+12]= {0};
+  mp_limb_t z1f[12+1];
+  mp_limb_t z1s[12+1];
+  mp_limb_t z3[24];
+  const mp_limb_t *op1_hi = PTR(op1) + 12;
+  const mp_limb_t *op2_hi = PTR(op2) + 12;
+  const mp_limb_t *op1_lo = PTR(op1);
+  const mp_limb_t *op2_lo = PTR(op2);
+  const mp_limb_t *z1_hi = z1 + 12;
+  const mp_limb_t *z1_lo = z1;
+  mp_limb_t carry;
+
+  /* make all operands of the same width */
+  _mpz_realloc(rop, 24);
+  _mpz_realloc(op1, 24);
+  _mpz_realloc(op2, 24);
+  SIZ(rop) = SIZ(op1) = SIZ(op2) = 24;
+
+  mpn_mul_n(z2, op1_hi, op2_hi, 12);
+  z2[24] = z2[25] = 0;
+  mpn_mul_n(z0, op1_lo, op2_lo, 12);
+  z0[24] = z0[25] = 0;
+
+  carry = mpn_add_n(z1f, op1_lo, op1_hi, 12);
+  z1f[12] = carry;
+  carry = mpn_add_n(z1s, op2_lo, op2_hi, 12);
+  z1s[12] = carry;
+  mpn_mul_n(z1, z1f, z1s, 12+1);
+  mpn_sub_n(z1, z1, z2, 24+2);
+  mpn_sub_n(z1, z1, z0, 24+2);
+
+  mpn_add_n(z3, z2, z1_hi, 24);
+  carry = mpn_mul_1(PTR(rop), z3, 24, gg);
+  carry += mpn_add_n(PTR(rop), PTR(rop), z0, 24);
+  carry += mpn_add_n(PTR(rop)+12, PTR(rop)+12, z1_lo, 12);
+  mpn_add_1(PTR(rop), PTR(rop), 24, carry*gg);
+
+  MPN_NORMALIZE(PTR(rop), SIZ(rop));
+}

+ 13 - 0
src/group.h

@@ -11,6 +11,8 @@ extern const char* p_str;
 extern mpz_t p, q;
 extern const uint64_t gg;
 
+typedef __uint128_t uint128_t;
+
 void group_init();
 void group_clear();
 
@@ -20,6 +22,16 @@ void group_clear();
 
 #define SIZ(x) ((x)->_mp_size)
 #define PTR(x) ((x)->_mp_d)
+#define MPN_COPY(dst, src, l) \
+  do {                                                  \
+    for (int i = 0; i < l; i++) (dst)[i] = (src)[i]; \
+  } while(0)
+
+#define MPN_ZERO(dst, l)                                \
+  do {                                                  \
+    for (size_t i = 0; i < l; i++) (dst)[i] = 0;        \
+  } while(0)
+
 #define MPN_NORMALIZE(DST, NLIMBS)                                      \
   do {									\
     while (1)								\
@@ -62,5 +74,6 @@ void remp(mpz_t rop)
 }
 
 void powmp_ui(mpz_t rop, const mpz_t base, uint64_t exp);
+void mul_modp(mpz_t rop, mpz_t op1, mpz_t op2);
 
 #define mpz_mul_modp(rop, op1, op2) mpz_mul(rop, op1, op2); remp(rop);

+ 38 - 0
src/group_test.c

@@ -0,0 +1,38 @@
+#include <assert.h>
+
+#include <gmp.h>
+
+#include "group.h"
+#include "entropy.h"
+
+mpz_t test, expected, x, y;
+
+
+int main()
+{
+  group_init();
+  mpz_entropy_init();
+  mpz_inits(test, expected, x, y, NULL);
+
+  for (int i = 0; i < 1e6; i++) {
+    mpz_urandomm(x, _rstate, p);
+    mpz_urandomm(y, _rstate, p);
+
+    mpz_mul(expected, x, y);
+    mpz_mod(expected, expected, p);
+    mul_modp(test, y, x);
+    if (mpz_cmp(test, expected)) {
+
+      gmp_printf("%lu %lu\n%lu %lu\n",
+                 PTR(test)[1], PTR(test)[0],
+                 PTR(expected)[1], PTR(expected)[0]);
+      assert(0);
+    }
+  }
+
+
+  mpz_clears(test, expected, x, y, NULL);
+  group_clear();
+
+  return 0;
+}

+ 15 - 16
src/rms.c

@@ -17,6 +17,7 @@
 
 INIT_TIMEIT(CLOCK_PROCESS_CPUTIME_ID);
 
+
 static inline
 uint32_t mul_single(const elgamal_cipher_t c,
                     const uint32_t x,
@@ -24,9 +25,7 @@ uint32_t mul_single(const elgamal_cipher_t c,
 {
   mpz_t op1, op2;
   mpz_inits(op1, op2, NULL);
-  //mpz_powm(op1, c1, cx, p);
   /* first block */
-
   fb_powmp_ui(op1, c->fb_c1, cx->_mp_d[0]);
 
   /* second block */
@@ -48,7 +47,6 @@ uint32_t mul_single(const elgamal_cipher_t c,
 void hss_mul(ssl2_t rop, const ssl1_t sl1, const ssl2_t sl2)
 {
   uint32_t converted;
-
   rop->x = mul_single(sl1->w, sl2->x, sl2->cx);
 
   mpz_set_ui(rop->cx, 0);
@@ -97,25 +95,26 @@ int main()
   ssl2_init(t1);
   ssl2_init(t2);
 
-  for (int i = 0; i <  (int) 1e2; i++) {
-    mpz_urandomb(y, _rstate, 1);
-    mpz_urandomb(x, _rstate, 1);
-    /* mpz_set_ui(x, 1); */
-    /* mpz_set_ui(y, 1); */
+  mpz_urandomb(y, _rstate, 1);
+  mpz_urandomb(x, _rstate, 1);
+  /* mpz_set_ui(x, 1); */
+  /* mpz_set_ui(y, 1); */
 
-    ssl2_share(s1, s2, x, key->sk);
-    ssl2_open(test, s1, s2);
-    assert(!mpz_cmp(test, x));
+  ssl2_share(s1, s2, x, key->sk);
+  ssl2_open(test, s1, s2);
+  assert(!mpz_cmp(test, x));
 
-    START_TIMEIT();
-    ssl1_share(r1, r2, y, key);
-    END_TIMEIT();
+  ssl1_share(r1, r2, y, key);
+
+  ssl1_open(test, r1, r2, key);
+  assert(!mpz_cmp_ui(test, mpz_cmp_ui(y, 0) ? 2 : 1));
 
-    ssl1_open(test, r1, r2, key);
-    assert(!mpz_cmp_ui(test, mpz_cmp_ui(y, 0) ? 2 : 1));
 
 
+  for (int i = 0; i <  (int) 1e2; i++) {
+    START_TIMEIT();
     hss_mul(t1, r1, s1);
+    END_TIMEIT();
     hss_mul(t2, r2, s2);
 #ifndef NDEBUG
     gmp_printf("%Zx %Zx\n", x, y);