#include // arc4random_buf #include "online.hpp" #include "mpcops.hpp" #include "rdpf.hpp" #include "duoram.hpp" #include "cdpf.hpp" static void online_test(MPCIO &mpcio, yield_t &yield, const PRACOptions &opts, char **args) { nbits_t nbits = VALUE_BITS; if (*args) { nbits = atoi(*args); } size_t memsize = 9; MPCTIO tio(mpcio, 0); bool is_server = (mpcio.player == 2); RegAS *A = new RegAS[memsize]; value_t V; RegBS F0, F1; RegXS X; if (!is_server) { A[0].randomize(); A[1].randomize(); F0.randomize(); A[4].randomize(); F1.randomize(); A[6].randomize(); A[7].randomize(); X.randomize(); arc4random_buf(&V, sizeof(V)); printf("A:\n"); for (size_t i=0; i coroutines; coroutines.emplace_back( [&](yield_t &yield) { mpc_mul(tio, yield, A[2], A[0], A[1], nbits); }); coroutines.emplace_back( [&](yield_t &yield) { mpc_valuemul(tio, yield, A[3], V, nbits); }); coroutines.emplace_back( [&](yield_t &yield) { mpc_flagmult(tio, yield, A[5], F0, A[4], nbits); }); coroutines.emplace_back( [&](yield_t &yield) { mpc_oswap(tio, yield, A[6], A[7], F1, nbits); }); coroutines.emplace_back( [&](yield_t &yield) { mpc_xs_to_as(tio, yield, A[8], X, nbits); }); run_coroutines(yield, coroutines); if (!is_server) { printf("\n"); printf("A:\n"); for (size_t i=0; i> peer_scaled_xor >> peer_scaled_sum; peer_scaled_sum += dpf.scaled_sum; peer_scaled_xor ^= dpf.scaled_xor; } for (address_t x=0;x<(address_t(1)<> peer_ub >> peer_ua >> peer_sx >> peer_sa; ub ^= peer_ub; ua += peer_ua; sx ^= peer_sx; sa += peer_sa; if (ub.bshare || ua.ashare || sx.xshare || sa.ashare) { printf("**** %x %016lx %016lx %016lx\n", ub.bshare, ua.ashare, sx.xshare, sa.ashare); printf("SCALE %016lx %016lx\n", peer_scaled_xor.xshare, peer_scaled_sum.ashare); } } } printf("\n"); } } tio.send(); }); } pool.join(); } static void rdpf_timing(MPCIO &mpcio, yield_t &yield, const PRACOptions &opts, char **args) { nbits_t depth=6; if (*args) { depth = atoi(*args); ++args; } int num_threads = opts.num_threads; boost::asio::thread_pool pool(num_threads); for (int thread_num = 0; thread_num < num_threads; ++thread_num) { boost::asio::post(pool, [&mpcio, &yield, thread_num, depth] { MPCTIO tio(mpcio, thread_num); size_t &aes_ops = tio.aes_ops(); if (mpcio.player == 2) { RDPFPair dp = tio.rdpfpair(yield, depth); for (int i=0;i<2;++i) { RDPF &dpf = dp.dpf[i]; dpf.expand(aes_ops); RegXS scaled_xor; for (address_t x=0;x<(address_t(1)< static void duoram_test(MPCIO &mpcio, yield_t &yield, const PRACOptions &opts, char **args) { nbits_t depth=6; address_t share=arc4random(); if (*args) { depth = atoi(*args); ++args; } if (*args) { share = atoi(*args); ++args; } share &= ((address_t(1)< oram(mpcio.player, size); auto A = oram.flat(tio, yield); RegAS aidx; aidx.ashare = share; T M; if (tio.player() == 0) { M.set(0xbabb0000); } else { M.set(0x0000a66e); } RegXS xidx; xidx.xshare = share; T N; if (tio.player() == 0) { N.set(0xdead0000); } else { N.set(0x0000beef); } // Writing and reading with additively shared indices printf("Updating\n"); A[aidx] += M; printf("Reading\n"); T Aa = A[aidx]; // Writing and reading with XOR shared indices printf("Updating\n"); A[xidx] += N; printf("Reading\n"); T Ax = A[xidx]; T Ae; // Writing and reading with explicit indices if (depth > 2) { A[5] += Aa; Ae = A[6]; } if (depth <= 10) { oram.dump(); auto check = A.reconstruct(); if (tio.player() == 0) { for (address_t i=0;i> peer_xsh >> peer_lt >> peer_eq >> peer_gt; lt ^= peer_lt; eq ^= peer_eq; gt ^= peer_gt; xsh += peer_xsh; int lti = int(lt.bshare); int eqi = int(eq.bshare); int gti = int(gt.bshare); x = xsh.share(); printf(": %d %d %d ", lti, eqi, gti); bool signbit = (x >> 63); if (lti + eqi + gti != 1) { printf("INCONSISTENT"); res = 0; } else if (x == 0 && eqi) { printf("="); } else if (!signbit && gti) { printf(">"); } else if (signbit && lti) { printf("<"); } else { printf("INCORRECT"); res = 0; } } printf("\n"); } return res; } static int compare_test_target(MPCTIO &tio, yield_t &yield, value_t target, value_t x) { int res = 1; res &= compare_test_one(tio, yield, target, x); res &= compare_test_one(tio, yield, target, 0); res &= compare_test_one(tio, yield, target, 1); res &= compare_test_one(tio, yield, target, 15); res &= compare_test_one(tio, yield, target, 16); res &= compare_test_one(tio, yield, target, 17); res &= compare_test_one(tio, yield, target, -1); res &= compare_test_one(tio, yield, target, -15); res &= compare_test_one(tio, yield, target, -16); res &= compare_test_one(tio, yield, target, -17); res &= compare_test_one(tio, yield, target, (value_t(1)<<63)); res &= compare_test_one(tio, yield, target, (value_t(1)<<63)+1); res &= compare_test_one(tio, yield, target, (value_t(1)<<63)-1); return res; } static void compare_test(MPCIO &mpcio, yield_t &yield, const PRACOptions &opts, char **args) { value_t target, x; arc4random_buf(&target, sizeof(target)); arc4random_buf(&x, sizeof(x)); if (*args) { target = strtoull(*args, NULL, 16); ++args; } if (*args) { x = strtoull(*args, NULL, 16); ++args; } int num_threads = opts.num_threads; boost::asio::thread_pool pool(num_threads); for (int thread_num = 0; thread_num < num_threads; ++thread_num) { boost::asio::post(pool, [&mpcio, &yield, thread_num, &target, &x] { MPCTIO tio(mpcio, thread_num); int res = 1; res &= compare_test_target(tio, yield, target, x); res &= compare_test_target(tio, yield, 0, x); res &= compare_test_target(tio, yield, 1, x); res &= compare_test_target(tio, yield, 15, x); res &= compare_test_target(tio, yield, 16, x); res &= compare_test_target(tio, yield, 17, x); res &= compare_test_target(tio, yield, -1, x); res &= compare_test_target(tio, yield, -15, x); res &= compare_test_target(tio, yield, -16, x); res &= compare_test_target(tio, yield, -17, x); res &= compare_test_target(tio, yield, (value_t(1)<<63), x); res &= compare_test_target(tio, yield, (value_t(1)<<63)+1, x); res &= compare_test_target(tio, yield, (value_t(1)<<63)-1, x); tio.send(); if (tio.player() == 0) { if (res == 1) { printf("All tests passed!\n"); } else { printf("TEST FAILURES\n"); } } }); } pool.join(); } static void sort_test(MPCIO &mpcio, yield_t &yield, const PRACOptions &opts, char **args) { nbits_t depth=6; if (*args) { depth = atoi(*args); ++args; } int num_threads = opts.num_threads; boost::asio::thread_pool pool(num_threads); for (int thread_num = 0; thread_num < num_threads; ++thread_num) { boost::asio::post(pool, [&mpcio, &yield, thread_num, depth] { address_t size = address_t(1)< oram(mpcio.player, size); auto A = oram.flat(tio, yield); A.explicitonly(true); // Initialize the memory to random values in parallel std::vector coroutines; for (address_t i=0; i>= 1; nbits_t depth=6; if (*args) { depth = atoi(*args); ++args; } if (*args) { target = strtoull(*args, NULL, 16); ++args; } int num_threads = opts.num_threads; boost::asio::thread_pool pool(num_threads); for (int thread_num = 0; thread_num < num_threads; ++thread_num) { boost::asio::post(pool, [&mpcio, &yield, thread_num, depth, target] { address_t size = address_t(1)<> tshare; } // Create a random database and sort it // size_t &aes_ops = tio.aes_ops(); Duoram oram(mpcio.player, size); auto A = oram.flat(tio, yield); A.explicitonly(true); // Initialize the memory to random values in parallel std::vector coroutines; for (address_t i=0; i> peer_tindex; tindex += peer_tindex; } if (depth <= 10) { auto check = A.reconstruct(); if (tio.player() == 0) { for (address_t i=0;i(mpcio, yield, opts, args); } else { duoram_test(mpcio, yield, opts, args); } } else if (!strcmp(*args, "cdpftest")) { ++args; cdpf_test(mpcio, yield, opts, args); } else if (!strcmp(*args, "cmptest")) { ++args; compare_test(mpcio, yield, opts, args); } else if (!strcmp(*args, "sorttest")) { ++args; sort_test(mpcio, yield, opts, args); } else if (!strcmp(*args, "bsearch")) { ++args; bsearch_test(mpcio, yield, opts, args); } else { std::cerr << "Unknown mode " << *args << "\n"; } }); }