Bladeren bron

Single-input evaluation of DPFs

Ian Goldberg 1 jaar geleden
bovenliggende
commit
6d92b7149b
4 gewijzigde bestanden met toevoegingen van 122 en 11 verwijderingen
  1. 2 0
      Makefile
  2. 25 10
      online.cpp
  3. 31 0
      rdpf.cpp
  4. 64 1
      rdpf.hpp

+ 2 - 0
Makefile

@@ -30,7 +30,9 @@ depend:
 prac.o: mpcio.hpp types.hpp preproc.hpp online.hpp
 mpcio.o: mpcio.hpp types.hpp rdpf.hpp coroutine.hpp bitutils.hpp
 preproc.o: types.hpp coroutine.hpp mpcio.hpp preproc.hpp rdpf.hpp
+preproc.o: bitutils.hpp
 online.o: online.hpp mpcio.hpp types.hpp mpcops.hpp coroutine.hpp rdpf.hpp
+online.o: bitutils.hpp
 mpcops.o: mpcops.hpp types.hpp mpcio.hpp coroutine.hpp bitutils.hpp
 rdpf.o: rdpf.hpp mpcio.hpp types.hpp coroutine.hpp bitutils.hpp mpcops.hpp
 rdpf.o: aes.hpp prg.hpp

+ 25 - 10
online.cpp

@@ -163,20 +163,35 @@ static void rdpf_test(MPCIO &mpcio, int num_threads, char **args)
     for (int thread_num = 0; thread_num < num_threads; ++thread_num) {
         boost::asio::post(pool, [&mpcio, thread_num, depth] {
             MPCTIO tio(mpcio, thread_num);
+            size_t &op_counter = tio.aes_ops();
             if (mpcio.player == 2) {
                 RDPFPair dp = tio.rdpfpair(depth);
-                printf("usi0 = %016lx\n", dp.dpf[0].unit_sum_inverse);
-                printf("ss0  = %016lx\n", dp.dpf[0].scaled_sum.ashare);
-                printf("usi1 = %016lx\n", dp.dpf[1].unit_sum_inverse);
-                printf("ss1  = %016lx\n", dp.dpf[1].scaled_sum.ashare);
+                for (int i=0;i<2;++i) {
+                    const RDPF &dpf = dp.dpf[i];
+                    for (address_t x=0;x<(address_t(1)<<depth);++x) {
+                        DPFnode leaf = dpf.leaf(x, op_counter);
+                        RegBS ub = dpf.unit_bs(leaf);
+                        RegAS ua = dpf.unit_as(leaf);
+                        RegXS sx = dpf.scaled_xs(leaf);
+                        RegAS sa = dpf.scaled_as(leaf);
+                        printf("%04x %x %016lx %016lx %016lx\n", x,
+                            ub.bshare, ua.ashare, sx.xshare, sa.ashare);
+                    }
+                }
             } else {
                 RDPFTriple dt = tio.rdpftriple(depth);
-                printf("usi0 = %016lx\n", dt.dpf[0].unit_sum_inverse);
-                printf("ss0  = %016lx\n", dt.dpf[0].scaled_sum.ashare);
-                printf("usi1 = %016lx\n", dt.dpf[1].unit_sum_inverse);
-                printf("ss1  = %016lx\n", dt.dpf[1].scaled_sum.ashare);
-                printf("usi2 = %016lx\n", dt.dpf[2].unit_sum_inverse);
-                printf("ss2  = %016lx\n", dt.dpf[2].scaled_sum.ashare);
+                for (int i=0;i<3;++i) {
+                    const RDPF &dpf = dt.dpf[i];
+                    for (address_t x=0;x<(address_t(1)<<depth);++x) {
+                        DPFnode leaf = dpf.leaf(x, op_counter);
+                        RegBS ub = dpf.unit_bs(leaf);
+                        RegAS ua = dpf.unit_as(leaf);
+                        RegXS sx = dpf.scaled_xs(leaf);
+                        RegAS sa = dpf.scaled_as(leaf);
+                        printf("%04x %x %016lx %016lx %016lx\n", x,
+                            ub.bshare, ua.ashare, sx.xshare, sa.ashare);
+                    }
+                }
             }
         });
     }

+ 31 - 0
rdpf.cpp

@@ -62,6 +62,7 @@ RDPF::RDPF(MPCTIO &tio, yield_t &yield,
     // Ensure the flag bits (the lsb of each node) are different
     seed = set_lsb(seed, !!player);
     cfbits = 0;
+    whichhalf = (player == 1);
 
     // The root level is just the seed
     nbits_t level = 0;
@@ -270,6 +271,36 @@ size_t RDPF::size() const
     return size(depth);
 }
 
+// Descend from a node at depth parentdepth to one of its children
+// whichchild = 0: left child
+// whichchild = 1: right child
+DPFnode RDPF::descend(const DPFnode parent, nbits_t parentdepth,
+    bit_t whichchild, size_t &op_counter) const
+{
+    DPFnode prgout;
+    bool flag = get_lsb(parent);
+    prg(prgout, parent, whichchild, op_counter);
+    if (flag) {
+        DPFnode CW = cw[parentdepth];
+        bit_t cfbit = !!(cfbits & (value_t(1)<<parentdepth));
+        DPFnode CWR = CW ^ lsb128_mask[cfbit];
+        prgout ^= (whichchild ? CWR : CW);
+    }
+    return prgout;
+}
+
+// Get the leaf node for the given input
+DPFnode RDPF::leaf(address_t input, size_t &op_counter) const
+{
+    nbits_t totdepth = depth();
+    DPFnode node = seed;
+    for (nbits_t d=0;d<totdepth;++d) {
+        bit_t dir = !!(input & (address_t(1)<<(totdepth-d-1)));
+        node = descend(node, d, dir, op_counter);
+    }
+    return node;
+}
+
 // Construct three RDPFs of the given depth all with the same randomly
 // generated target index.
 RDPFTriple::RDPFTriple(MPCTIO &tio, yield_t &yield,

+ 64 - 1
rdpf.hpp

@@ -7,10 +7,13 @@
 #include "mpcio.hpp"
 #include "coroutine.hpp"
 #include "types.hpp"
+#include "bitutils.hpp"
 
 struct RDPF {
     // The 128-bit seed
     DPFnode seed;
+    // Which half of the DPF are we?
+    bit_t whichhalf;
     // correction words; the depth of the DPF is the length of this
     // vector
     std::vector<DPFnode> cw;
@@ -52,6 +55,59 @@ struct RDPF {
 
     // The depth
     inline nbits_t depth() const { return cw.size(); }
+
+    // Descend from a node at depth parentdepth to one of its children
+    // whichchild = 0: left child
+    // whichchild = 1: right child
+    //
+    // Cost: 1 AES operation
+    DPFnode descend(const DPFnode parent, nbits_t parentdepth,
+        bit_t whichchild, size_t &op_counter) const;
+
+    // Get the leaf node for the given input
+    //
+    // Cost: depth AES operations
+    DPFnode leaf(address_t input, size_t &op_counter) const;
+
+    // Get the bit-shared unit vector entry from the leaf node
+    inline RegBS unit_bs(DPFnode leaf) const {
+        RegBS b;
+        b.bshare = get_lsb(leaf);
+        return b;
+    }
+
+    // Get the additive-shared unit vector entry from the leaf node
+    inline RegAS unit_as(DPFnode leaf) const {
+        RegAS a;
+        value_t lowword = value_t(_mm_cvtsi128_si64x(leaf));
+        if (whichhalf == 1) {
+            lowword = -lowword;
+        }
+        a.ashare = lowword * unit_sum_inverse;
+        return a;
+    }
+
+    // Get the XOR-shared scaled vector entry from the leaf ndoe
+    inline RegXS scaled_xs(DPFnode leaf) const {
+        RegXS x;
+        value_t highword =
+            value_t(_mm_cvtsi128_si64x(_mm_srli_si128(leaf,8)));
+        x.xshare = highword;
+        return x;
+    }
+
+    // Get the additive-shared scaled vector entry from the leaf ndoe
+    inline RegAS scaled_as(DPFnode leaf) const {
+        RegAS a;
+        value_t highword =
+            value_t(_mm_cvtsi128_si64x(_mm_srli_si128(leaf,8)));
+        if (whichhalf == 1) {
+            highword = -highword;
+        }
+        a.ashare = highword;
+        return a;
+    }
+
 };
 
 // I/O for RDPFs
@@ -61,7 +117,10 @@ T& operator>>(T &is, RDPF &rdpf)
 {
     is.read((char *)&rdpf.seed, sizeof(rdpf.seed));
     uint8_t depth;
+    // The whichhalf bit is the high bit of depth
     is.read((char *)&depth, sizeof(depth));
+    rdpf.whichhalf = !!(depth & 0x80);
+    depth &= 0x7f;
     assert(depth <= ADDRESS_MAX_BITS);
     rdpf.cw.clear();
     for (uint8_t i=0; i<depth; ++i) {
@@ -85,7 +144,11 @@ T& operator<<(T &os, const RDPF &rdpf)
     os.write((const char *)&rdpf.seed, sizeof(rdpf.seed));
     uint8_t depth = rdpf.cw.size();
     assert(depth <= ADDRESS_MAX_BITS);
-    os.write((const char *)&depth, sizeof(depth));
+    // The whichhalf bit is the high bit of depth
+    uint8_t whichhalf_and_depth = depth |
+        (uint8_t(rdpf.whichhalf)<<7);
+    os.write((const char *)&whichhalf_and_depth,
+        sizeof(whichhalf_and_depth));
     for (uint8_t i=0; i<depth; ++i) {
         os.write((const char *)&rdpf.cw[i], sizeof(rdpf.cw[i]));
     }