#include "Auth/MAC_Check.h" #include "Auth/Subroutines.h" #include "Exceptions/Exceptions.h" #include "Tools/random.h" #include "Tools/time-func.h" #include "Tools/int.h" #include "Tools/benchmarking.h" #include template const char* TreeSum::mc_timer_names[] = { "sending", "receiving and adding", "broadcasting", "receiving summed values", "random seed", "commit and open", "wait for summer thread", "receiving", "summing", "waiting for select()" }; template MAC_Check_::MAC_Check_(const T& ai, int opening_sum, int max_broadcast, int send_player) : TreeSum(opening_sum, max_broadcast, send_player) { popen_cnt=0; this->alphai=ai; vals.reserve(2 * POPEN_MAX); macs.reserve(2 * POPEN_MAX); } template MAC_Check_::~MAC_Check_() { } template void MAC_Check_::PrepareSending(vector& values, const vector& S) { values.resize(S.size()); for (unsigned int i=0; i void MAC_Check_::POpen_Begin(vector& values,const vector& S,const Player& P) { AddToMacs(S); PrepareSending(values, S); this->start(values, P); this->values_opened += S.size(); } template void MAC_Check_::POpen_End(vector& values,const vector& S,const Player& P) { S.size(); this->finish(values, P); popen_cnt += values.size(); CheckIfNeeded(P); /* not compatible with continuous communication send_player++; if (send_player==P.num_players()) { send_player=0; } */ } template void MAC_Check_Base::POpen(vector& values,const vector& S,const Player& P) { POpen_Begin(values, S, P); POpen_End(values, S, P); } template typename T::open_type MAC_Check_Base::POpen(const T& secret, const Player& P) { vector opened; POpen(opened, {secret}, P); return opened[0]; } template void MAC_Check_::AddToMacs(const vector& shares) { for (unsigned int i = 0; i < shares.size(); i++) macs.push_back(shares[i].get_mac()); #ifdef DEBUG_MAC if (shares.size()) cout << "adding macs " << shares.back() << " / " << shares.back().get_mac() << " / " << macs.back() << endl; #endif } template void MAC_Check_::AddToValues(vector& values) { vals.insert(vals.end(), values.begin(), values.end()); } template void MAC_Check_::GetValues(vector& values) { int size = values.size(); if (popen_cnt + size > int(vals.size())) { stringstream ss; ss << "wanted " << values.size() << " values from " << popen_cnt << ", only " << vals.size() << " in store"; throw out_of_range(ss.str()); } values.clear(); typename vector::iterator first = vals.begin() + popen_cnt; values.insert(values.end(), first, first + size); } template void MAC_Check_::CheckIfNeeded(const Player& P) { if (WaitingForCheck() >= POPEN_MAX) Check(P); } template void MAC_Check_::AddToCheck(const U& share, const T& value, const Player& P) { macs.push_back(share.get_mac()); vals.push_back(value); popen_cnt++; CheckIfNeeded(P); } template void MAC_Check_::Check(const Player& P) { if (WaitingForCheck() == 0) return; //cerr << "In MAC Check : " << popen_cnt << endl; octet seed[SEED_SIZE]; this->timers[SEED].start(); Create_Random_Seed(seed,P,SEED_SIZE); this->timers[SEED].stop(); PRNG G; G.SetSeed(seed); U sj; T a,gami,h,temp; a.assign_zero(); gami.assign_zero(); vector tau(P.num_players()); for (int i=0; ialphai,a); tau[P.my_num()].sub(gami,temp); //cerr << "\tCommit and Open" << endl; this->timers[COMMIT].start(); Commit_And_Open(tau,P); this->timers[COMMIT].stop(); //cerr << "\tFinal Check" << endl; T t; t.assign_zero(); for (int i=0; i int mc_base_id(int function_id, int thread_num) { return (function_id << 28) + ((T::field_type() + 1) << 24) + (thread_num << 16); } template MAC_Check_Z2k::MAC_Check_Z2k(const T& ai, int opening_sum, int max_broadcast, int send_player) : MAC_Check_(ai, opening_sum, max_broadcast, send_player), prep(0) { } template MAC_Check_Z2k::MAC_Check_Z2k(const T& ai, Names& Nms, int thread_num) : MAC_Check_Z2k(ai) { (void) Nms, (void) thread_num; } template void MAC_Check_Z2k::AddToCheck(const W& share, const T& value, const Player& P) { shares.push_back(share.get_share()); MAC_Check_::AddToCheck(share, value, P); } template void MAC_Check_Z2k::AddToMacs(const vector& shares) { for (auto& share : shares) this->shares.push_back(share.get_share()); MAC_Check_::AddToMacs(shares); #ifdef DEBUG_MAC cout << "add share " << shares.back() << " / " << this->shares.back() << endl; #endif } template void MAC_Check_Z2k::PrepareSending(vector& values, const vector& S) { values.clear(); values.reserve(S.size()); for (auto& share : S) values.push_back(V(share.get_share())); } template W MAC_Check_Z2k::get_random_element() { if (random_elements.size() > 0) { W res = random_elements.back(); random_elements.pop_back(); return res; } else { if (prep) return prep->get_random(); else { insecure("random dummy"); return {}; } } } template void MAC_Check_Z2k::set_random_element(const W& random_element) { random_elements.push_back(random_element); } template void MAC_Check_Z2k::set_prep(MascotPrep& prep) { this->prep = &prep; } template void MAC_Check_Z2k::Check(const Player& P) { if (this->WaitingForCheck() == 0) return; #ifdef DEBUG_MAC cout << "Checking " << shares[0] << " " << this->vals[0] << " " << this->macs[0] << endl; #endif int k = V::N_BITS; octet seed[SEED_SIZE]; Create_Random_Seed(seed,P,SEED_SIZE); PRNG G; G.SetSeed(seed); T y, mj; y.assign_zero(); mj.assign_zero(); vector chi; for (int i = 0; i < this->popen_cnt; ++i) { U temp_chi; temp_chi.randomize(G); T xi = this->vals[i]; y += xi * temp_chi; T mji = this->macs[i]; mj += temp_chi * mji; chi.push_back(temp_chi); } W r = get_random_element(); T lj = r.get_mac(); U pj; pj.assign_zero(); for (int i = 0; i < this->popen_cnt; ++i) { T xji = shares[i]; V xbarji = xji; U pji = U((xji - xbarji) >> k); pj += chi[i] * pji; } pj += U(r.get_share()); U pbar(pj); vector pj_stream(P.num_players()); pj.pack(pj_stream[P.my_num()]); P.Broadcast_Receive(pj_stream, true); for (int j=0; jalphai * y) - (((this->alphai * pbar)) << k) + (lj << k); vector zjs(P.num_players()); zjs[P.my_num()] = zj; Commit_And_Open(zjs, P); T zj_sum; zj_sum.assign_zero(); for (int i = 0; i < P.num_players(); ++i) zj_sum += zjs[i]; this->vals.erase(this->vals.begin(), this->vals.begin() + this->popen_cnt); this->macs.erase(this->macs.begin(), this->macs.begin() + this->popen_cnt); this->shares.erase(this->shares.begin(), this->shares.begin() + this->popen_cnt); this->popen_cnt=0; if (!zj_sum.is_zero()) { throw mac_fail(); } } template Separate_MAC_Check::Separate_MAC_Check(const T& ai, Names& Nms, int thread_num, int opening_sum, int max_broadcast, int send_player) : MAC_Check(ai, opening_sum, max_broadcast, send_player), check_player(Nms, mc_base_id(1, thread_num)) { } template void Separate_MAC_Check::Check(const Player& P) { P.my_num(); MAC_Check::Check(check_player); } template void* run_summer_thread(void* summer) { ((Summer*) summer)->run(); return 0; } template Parallel_MAC_Check::Parallel_MAC_Check(const T& ai, Names& Nms, int thread_num, int opening_sum, int max_broadcast, int base_player) : Separate_MAC_Check(ai, Nms, thread_num, opening_sum, max_broadcast, base_player), send_player(Nms, mc_base_id(2, thread_num)), send_base_player(base_player) { int sum_players = Nms.num_players(); Player* summer_send_player = &send_player; for (int i = 0; ; i++) { int last_sum_players = sum_players; sum_players = (sum_players - 2 + opening_sum) / opening_sum; int next_sum_players = (sum_players - 2 + opening_sum) / opening_sum; if (sum_players == 0) break; Player* summer_receive_player = summer_send_player; summer_send_player = new PlainPlayer(Nms, mc_base_id(3, thread_num)); summers.push_back(new Summer(sum_players, last_sum_players, next_sum_players, summer_send_player, summer_receive_player, *this)); pthread_create(&(summers[i]->thread), 0, run_summer_thread, summers[i]); } receive_player = summer_send_player; } template Parallel_MAC_Check::~Parallel_MAC_Check() { for (unsigned int i = 0; i < summers.size(); i++) { summers[i]->input_queue.stop(); pthread_join(summers[i]->thread, 0); delete summers[i]; } } template void Parallel_MAC_Check::POpen_Begin(vector& values, const vector >& S, const Player& P) { values.size(); this->AddToMacs(S); int my_relative_num = positive_modulo(P.my_num() - send_base_player, P.num_players()); int sum_players = (P.num_players() - 2 + this->opening_sum) / this->opening_sum; int receiver = positive_modulo(send_base_player + my_relative_num % sum_players, P.num_players()); // use queue rather sending to myself if (receiver == P.my_num()) { for (unsigned int i = 0; i < S.size(); i++) values[i] = S[i].get_share(); summers.front()->share_queue.push(values); } else { this->os.reset_write_head(); for (unsigned int i=0; ios); this->timers[SEND].start(); send_player.send_to(receiver,this->os,true); this->timers[SEND].stop(); } for (unsigned int i = 0; i < summers.size(); i++) summers[i]->input_queue.push(S.size()); this->values_opened += S.size(); send_base_player = (send_base_player + 1) % send_player.num_players(); } template void Parallel_MAC_Check::POpen_End(vector& values, const vector >& S, const Player& P) { int last_size = 0; this->timers[WAIT_SUMMER].start(); summers.back()->output_queue.pop(last_size); this->timers[WAIT_SUMMER].stop(); if (int(values.size()) != last_size) { stringstream ss; ss << "stopopen wants " << values.size() << " values, but I have " << last_size << endl; throw Processor_Error(ss.str().c_str()); } if (this->base_player == P.my_num()) { value_queue.pop(values); if (int(values.size()) != last_size) throw Processor_Error("wrong number of local values"); else this->AddToValues(values); } this->MAC_Check::POpen_End(values, S, *receive_player); this->base_player = (this->base_player + 1) % send_player.num_players(); } template Direct_MAC_Check::Direct_MAC_Check(const T& ai, Names& Nms, int num) : Separate_MAC_Check(ai, Nms, num) { open_counter = 0; } template Direct_MAC_Check::~Direct_MAC_Check() { cerr << T::type_string() << " open counter: " << open_counter << endl; } template void Direct_MAC_Check::POpen_Begin(vector& values,const vector >& S,const Player& P) { values.resize(S.size()); this->os.reset_write_head(); for (unsigned int i=0; ios); this->timers[SEND].start(); P.send_all(this->os,true); this->timers[SEND].stop(); this->AddToMacs(S); for (unsigned int i=0; ivals.push_back(S[i].get_share()); } template void direct_add_openings(vector& values, const Player& P, vector& os) { for (unsigned int i=0; i(os[j].consume(T::size())); } template void Direct_MAC_Check::POpen_End(vector& values,const vector >& S,const Player& P) { S.size(); oss.resize(P.num_players()); this->GetValues(values); this->timers[RECV].start(); for (int j=0; jtimers[RECV].stop(); open_counter++; if (T::t() == 2) direct_add_openings(values, P, oss); else direct_add_openings(values, P, oss); for (unsigned int i = 0; i < values.size(); i++) this->vals[this->popen_cnt+i] = values[i]; this->popen_cnt += values.size(); this->CheckIfNeeded(P); } template Passing_MAC_Check::Passing_MAC_Check(const T& ai, Names& Nms, int num) : Separate_MAC_Check(ai, Nms, num) { } template void passing_add_openings(vector& values, octetStream& os) { octetStream new_os; for (unsigned int i=0; i void Passing_MAC_Check::POpen_Begin(vector& values,const vector >& S,const Player& P) { values.resize(S.size()); this->os.reset_write_head(); for (unsigned int i=0; ios); values[i] = S[i].get_share(); } this->AddToMacs(S); for (int i = 0; i < P.num_players() - 1; i++) { P.pass_around(this->os); if (T::t() == 2) passing_add_openings(values, this->os); else passing_add_openings(values, this->os); } for (unsigned int i = 0; i < values.size(); i++) { T tmp; tmp.unpack(this->os); this->vals.push_back(tmp); } } template void Passing_MAC_Check::POpen_End(vector& values,const vector >& S,const Player& P) { (void)S; this->GetValues(values); this->popen_cnt += values.size(); this->CheckIfNeeded(P); }