More honest-majority three-party computation (modulo prime and malicious binary).

This commit is contained in:
Marcel Keller
2018-11-30 15:14:43 +11:00
parent 69ffa077f2
commit ea59419de2
160 changed files with 3767 additions and 1661 deletions

1
.gitignore vendored
View File

@@ -30,6 +30,7 @@ tags
.project
.cproject
.settings
.pydevproject
# VS Code IDE #
###############

5
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "SimpleOT"]
path = SimpleOT
url = https://github.com/pascholl/SimpleOT
url = https://github.com/mkskeller/SimpleOT
[submodule "mpir"]
path = mpir
url = git://github.com/wbhart/mpir.git

View File

@@ -10,6 +10,8 @@
#include "Math/gfp.h"
#include "Math/gf2n.h"
#include "Math/BitVec.h"
#include "Math/Rep3Share.h"
#include "Math/MaliciousRep3Share.h"
#include <algorithm>
@@ -73,12 +75,19 @@ void MAC_Check<T>::POpen_End(vector<T>& values,const vector<Share<T> >& S,const
}
template<class T>
void MAC_Check<T>::POpen(vector<T>& values,const vector<Share<T> >& S,const Player& P)
void MAC_Check_Base<T>::POpen(vector<typename T::clear>& values,const vector<T>& S,const Player& P)
{
POpen_Begin(values, S, P);
POpen_End(values, S, P);
}
template<class T>
typename T::clear MAC_Check_Base<T>::POpen(const T& secret, const Player& P)
{
vector<typename T::clear> opened;
POpen(opened, {secret}, P);
return opened[0];
}
template<class T>
void MAC_Check<T>::AddToMacs(const vector<Share<T> >& shares)
@@ -446,5 +455,7 @@ template class Parallel_MAC_Check<gf2n_short>;
template class Passing_MAC_Check<gf2n_short>;
#endif
template class MAC_Check_Base<Integer>;
template class MAC_Check_Base<BitVec>;
template class MAC_Check_Base<Rep3Share<gfp>>;
template class MAC_Check_Base<Rep3Share<gf2n>>;
template class MAC_Check_Base<MaliciousRep3Share<gfp>>;
template class MAC_Check_Base<MaliciousRep3Share<gf2n>>;

View File

@@ -60,7 +60,7 @@ class MAC_Check_Base
{
protected:
/* MAC Share */
T alphai;
typename T::clear alphai;
public:
int values_opened;
@@ -72,12 +72,17 @@ public:
int number() const { return values_opened; }
const T& get_alphai() const { return alphai; }
const typename T::clear& get_alphai() const { return alphai; }
virtual void POpen_Begin(vector<typename T::clear>& values,const vector<T>& S,const Player& P) = 0;
virtual void POpen_End(vector<typename T::clear>& values,const vector<T>& S,const Player& P) = 0;
void POpen(vector<typename T::clear>& values,const vector<T>& S,const Player& P);
typename T::clear POpen(const T& secret, const Player& P);
};
template<class T>
class MAC_Check : public TreeSum<T>, public MAC_Check_Base<T>
class MAC_Check : public TreeSum<T>, public MAC_Check_Base<Share<T>>
{
protected:
@@ -107,7 +112,6 @@ class MAC_Check : public TreeSum<T>, public MAC_Check_Base<T>
*/
virtual void POpen_Begin(vector<T>& values,const vector<Share<T> >& S,const Player& P);
virtual void POpen_End(vector<T>& values,const vector<Share<T> >& S,const Player& P);
void POpen(vector<T>& values,const vector<Share<T> >& S,const Player& P);
void AddToCheck(const T& mac, const T& value, const Player& P);
virtual void Check(const Player& P);

66
Auth/MaliciousRepMC.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* MaliciousRepMC.h
*
*/
#ifndef AUTH_MALICIOUSREPMC_H_
#define AUTH_MALICIOUSREPMC_H_
#include "ReplicatedMC.h"
#include "GC/MaliciousRepSecret.h"
#include "GC/Machine.h"
template<class T>
class MaliciousRepMC : public ReplicatedMC<T>
{
protected:
typedef ReplicatedMC<T> super;
public:
virtual void POpen_Begin(vector<typename T::clear>& values,
const vector<T>& S, const Player& P);
virtual void POpen_End(vector<typename T::clear>& values,
const vector<T>& S, const Player& P);
virtual void Check(const Player& P);
};
template<class T>
class HashMaliciousRepMC : public MaliciousRepMC<T>
{
crypto_generichash_state* hash_state;
octetStream os;
public:
// emulate MAC_Check
HashMaliciousRepMC(const typename T::value_type& _, int __ = 0, int ___ = 0) : HashMaliciousRepMC()
{ (void)_; (void)__; (void)___; }
// emulate Direct_MAC_Check
HashMaliciousRepMC(const typename T::value_type& _, Names& ____, int __ = 0, int ___ = 0) : HashMaliciousRepMC()
{ (void)_; (void)__; (void)___; (void)____; }
HashMaliciousRepMC();
~HashMaliciousRepMC();
void POpen_End(vector<typename T::clear>& values,const vector<T>& S,const Player& P);
void Check(const Player& P);
};
template<class T>
class CommMaliciousRepMC : public MaliciousRepMC<T>
{
vector<octetStream> os;
public:
void POpen_Begin(vector<typename T::clear>& values, const vector<T>& S,
const Player& P);
void POpen_End(vector<typename T::clear>& values, const vector<T>& S,
const Player& P);
void Check(const Player& P);
};
#endif /* AUTH_MALICIOUSREPMC_H_ */

107
Auth/MaliciousRepMC.hpp Normal file
View File

@@ -0,0 +1,107 @@
/*
* MaliciousRepMC.cpp
*
*/
#include "MaliciousRepMC.h"
#include "GC/Machine.h"
#include "ReplicatedMC.hpp"
#include <stdlib.h>
template<class T>
void MaliciousRepMC<T>::POpen_Begin(vector<typename T::clear>& values,
const vector<T>& S, const Player& P)
{
super::POpen_Begin(values, S, P);
}
template<class T>
void MaliciousRepMC<T>::POpen_End(vector<typename T::clear>& values,
const vector<T>& S, const Player& P)
{
(void)values, (void)S, (void)P;
throw runtime_error("use subclass");
}
template<class T>
void MaliciousRepMC<T>::Check(const Player& P)
{
(void)P;
throw runtime_error("use subclass");
}
template<class T>
HashMaliciousRepMC<T>::HashMaliciousRepMC()
{
// deal with alignment issues
int error = posix_memalign((void**)&hash_state, 64, sizeof(crypto_generichash_state));
if (error)
throw runtime_error(string("failed to allocate hash state: ") + strerror(error));
crypto_generichash_init(hash_state, 0, 0, crypto_generichash_BYTES);
}
template<class T>
HashMaliciousRepMC<T>::~HashMaliciousRepMC()
{
free(hash_state);
}
template<class T>
void HashMaliciousRepMC<T>::POpen_End(vector<typename T::clear>& values,
const vector<T>& S, const Player& P)
{
ReplicatedMC<T>::POpen_End(values, S, P);
os.reset_write_head();
for (auto& value : values)
value.pack(os);
crypto_generichash_update(hash_state, os.get_data(), os.get_length());
}
template<class T>
void HashMaliciousRepMC<T>::Check(const Player& P)
{
unsigned char hash[crypto_generichash_BYTES];
crypto_generichash_final(hash_state, hash, sizeof hash);
crypto_generichash_init(hash_state, 0, 0, crypto_generichash_BYTES);
vector<octetStream> os(P.num_players());
os[P.my_num()].serialize(hash);
P.Broadcast_Receive(os);
for (int i = 0; i < P.num_players(); i++)
if (os[i] != os[P.my_num()])
throw mac_fail();
}
template<class T>
void CommMaliciousRepMC<T>::POpen_Begin(vector<typename T::clear>& values,
const vector<T>& S, const Player& P)
{
assert(T::length == 2);
(void)values;
os.resize(2);
for (auto& o : os)
o.reset_write_head();
for (auto& x : S)
for (int i = 0; i < 2; i++)
x[i].pack(os[1 - i]);
P.send_relative(os);
}
template<class T>
void CommMaliciousRepMC<T>::POpen_End(vector<typename T::clear>& values,
const vector<T>& S, const Player& P)
{
P.receive_relative(os);
if (os[0] != os[1])
throw mac_fail();
values.clear();
for (auto& x : S)
values.push_back(os[0].template get<BitVec>() + x.sum());
}
template<class T>
void CommMaliciousRepMC<T>::Check(const Player& P)
{
(void)P;
}

View File

@@ -9,17 +9,17 @@
#include "MAC_Check.h"
template <class T>
class ReplicatedMC : public MAC_Check_Base<typename T::value_type>
class ReplicatedMC : public MAC_Check_Base<T>
{
octetStream o;
public:
// emulate MAC_Check
ReplicatedMC(const gfp& _ = {}, int __ = 0, int ___ = 0) :
MAC_Check_Base<typename T::value_type>({})
ReplicatedMC(const typename T::value_type& _ = {}, int __ = 0, int ___ = 0)
{ (void)_; (void)__; (void)___; }
// emulate Direct_MAC_Check
ReplicatedMC(const gfp& _, Names& ____, int __ = 0, int ___ = 0) :
MAC_Check_Base<typename T::value_type>({})
ReplicatedMC(const typename T::value_type& _, Names& ____, int __ = 0, int ___ = 0)
{ (void)_; (void)__; (void)___; (void)____; }
void POpen_Begin(vector<typename T::clear>& values,const vector<T>& S,const Player& P);

View File

@@ -4,8 +4,6 @@
*/
#include "ReplicatedMC.h"
#include "GC/ReplicatedSecret.h"
#include "Math/Rep3Share.h"
template<class T>
void ReplicatedMC<T>::POpen_Begin(vector<typename T::clear>& values,
@@ -13,18 +11,17 @@ void ReplicatedMC<T>::POpen_Begin(vector<typename T::clear>& values,
{
assert(T::length == 2);
(void)values;
octetStream o;
o.reset_write_head();
for (auto& x : S)
x[0].pack(o);
P.send_relative(-1, o);
P.pass_around(o, -1);
}
template<class T>
void ReplicatedMC<T>::POpen_End(vector<typename T::clear>& values,
const vector<T>& S, const Player& P)
{
octetStream o;
P.receive_relative(1, o);
(void)P;
values.resize(S.size());
for (size_t i = 0; i < S.size(); i++)
{
@@ -33,6 +30,3 @@ void ReplicatedMC<T>::POpen_End(vector<typename T::clear>& values,
values[i] = S[i].sum() + tmp;
}
}
template class ReplicatedMC<Rep3Share>;
template class ReplicatedMC<GC::ReplicatedSecret>;

View File

@@ -63,6 +63,14 @@ int Open_Challenge(vector<unsigned int>& e,vector<octetStream>& Open_e,
template<class T>
void Create_Random(T& ans,const Player& P);
template<class T>
T Create_Random(const Player& P)
{
T res;
Create_Random(res, P);
return res;
}
/* Produce a random seed of length len */
void Create_Random_Seed(octet* seed,const Player& P,int len);

View File

@@ -6,22 +6,19 @@
#include "Math/gfp.h"
#include "Math/Share.h"
#include "Math/Rep3Share.h"
#include "GC/MaliciousRepSecret.h"
#include <fstream>
using namespace std;
template<class T>
void make_share(vector<Share<T> >& Sa,const T& a,int N,const T& key,PRNG& G);
void make_share(vector<Rep3Share>& Sa, const Integer& a, int N,
const Integer& key, PRNG& G);
template<class T>
void check_share(vector<Share<T> >& Sa,T& value,T& mac,int N,const T& key);
void check_share(vector<Rep3Share>& Sa, Integer& value, Integer& mac, int N,
const Integer& key);
void expand_byte(gf2n_short& a,int b);
void collapse_byte(int& b,const gf2n_short& a);
template<class T>
void check_share(vector<T>& Sa, typename T::clear& value,
typename T::value_type& mac, int N, const typename T::value_type& key);
// Generate MAC key shares
void generate_keys(const string& directory, int nplayers);
@@ -38,9 +35,9 @@ class Files
public:
ofstream* outf;
int N;
T key;
typename T::value_type key;
PRNG G;
Files(int N, const T& key, const string& prefix) : N(N), key(key)
Files(int N, const typename T::value_type& key, const string& prefix) : N(N), key(key)
{
outf = new ofstream[N];
for (int i=0; i<N; i++)
@@ -58,9 +55,9 @@ public:
{
delete[] outf;
}
void output_shares(const T& a)
void output_shares(const typename T::clear& a)
{
vector<Share<T> > Sa(N);
vector<T> Sa(N);
make_share(Sa,a,N,key,G);
for (int j=0; j<N; j++)
Sa[j].output(outf[j],false);

View File

@@ -29,20 +29,30 @@ void make_share(vector<Share<T> >& Sa,const T& a,int N,const T& key,PRNG& G)
Sa[N-1]=S;
}
void make_share(vector<Rep3Share>& Sa,
const Integer& a, int N, const Integer& key,
template<class T>
void make_share(FixedVec<T, 2>* Sa, const T& a, int N, PRNG& G);
template<class T>
inline void make_share(vector<T>& Sa,
const typename T::clear& a, int N, const typename T::value_type& key,
PRNG& G)
{
(void)key;
Sa.resize(N);
make_share(Sa.data(), a, N, G);
}
template<class T>
void make_share(FixedVec<T, 2>* Sa, const T& a, int N, PRNG& G)
{
assert(N == 3);
insecure("share generation", false);
Sa.resize(N);
FixedVec<Integer, 3> add_shares;
FixedVec<T, 3> add_shares;
// hack
add_shares.randomize_to_sum(a, G);
for (int i=0; i<N; i++)
{
FixedVec<Integer, 2> share;
FixedVec<T, 2> share;
share[0] = add_shares[(i + 1) % 3];
share[1] = add_shares[i];
Sa[i] = share;
@@ -73,9 +83,9 @@ void check_share(vector<Share<T> >& Sa,T& value,T& mac,int N,const T& key)
}
}
void check_share(vector<Rep3Share>& Sa,
Integer& value, Integer& mac, int N,
const Integer& key)
template<class T>
void check_share(vector<T>& Sa, typename T::clear& value,
typename T::value_type& mac, int N, const typename T::value_type& key)
{
assert(N == 3);
value = 0;
@@ -86,69 +96,20 @@ void check_share(vector<Rep3Share>& Sa,
{
auto share = Sa[i];
value += share[0];
if (share[1] != Sa[positive_modulo(i - 1, N)][0])
auto a = share[1];
auto b = Sa[positive_modulo(i - 1, N)][0];
if (a != b)
{
cout << a << " != " << b << endl;
cout << hex << a.debug() << " != " << b.debug() << endl;
for (int i = 0; i < N; i++)
cout << Sa[i] << endl;
throw bad_value("invalid replicated secret sharing");
}
}
}
template void make_share(vector<Share<gf2n> >& Sa,const gf2n& a,int N,const gf2n& key,PRNG& G);
template void make_share(vector<Share<gfp> >& Sa,const gfp& a,int N,const gfp& key,PRNG& G);
template void check_share(vector<Share<gf2n> >& Sa,gf2n& value,gf2n& mac,int N,const gf2n& key);
template void check_share(vector<Share<gfp> >& Sa,gfp& value,gfp& mac,int N,const gfp& key);
#ifdef USE_GF2N_LONG
template void make_share(vector<Share<gf2n_short> >& Sa,const gf2n_short& a,int N,const gf2n_short& key,PRNG& G);
template void check_share(vector<Share<gf2n_short> >& Sa,gf2n_short& value,gf2n_short& mac,int N,const gf2n_short& key);
#endif
// Expansion is by x=y^5+1 (as we embed GF(256) into GF(2^40)
void expand_byte(gf2n_short& a,int b)
{
gf2n_short x,xp;
x.assign(32+1);
xp.assign_one();
a.assign_zero();
while (b!=0)
{ if ((b&1)==1)
{ a.add(a,xp); }
xp.mul(x);
b>>=1;
}
}
// Have previously worked out the linear equations we need to solve
void collapse_byte(int& b,const gf2n_short& aa)
{
word w=aa.get();
int e35=(w>>35)&1;
int e30=(w>>30)&1;
int e25=(w>>25)&1;
int e20=(w>>20)&1;
int e15=(w>>15)&1;
int e10=(w>>10)&1;
int e5=(w>>5)&1;
int e0=w&1;
int a[8];
a[7]=e35;
a[6]=e30^a[7];
a[5]=e25^a[7];
a[4]=e20^a[5]^a[6]^a[7];
a[3]=e15^a[7];
a[2]=e10^a[3]^a[6]^a[7];
a[1]=e5^a[3]^a[5]^a[7];
a[0]=e0^a[1]^a[2]^a[3]^a[4]^a[5]^a[6]^a[7];
b=0;
for (int i=7; i>=0; i--)
{ b=b<<1;
b+=a[i];
}
}
void generate_keys(const string& directory, int nplayers)
inline void generate_keys(const string& directory, int nplayers)
{
PRNG G;
G.ReSeed();
@@ -166,14 +127,19 @@ void generate_keys(const string& directory, int nplayers)
}
}
inline string mac_filename(string directory, int playerno)
{
if (directory.empty())
directory = ".";
return directory + "/Player-MAC-Keys-P" + to_string(playerno);
}
template <class T>
void write_mac_keys(const string& directory, int i, int nplayers, gfp macp, T mac2)
{
ofstream outf;
stringstream filename;
if (directory.size())
filename << directory << "/";
filename << "Player-MAC-Keys-P" << i;
filename << mac_filename(directory, i);
cout << "Writing to " << filename.str().c_str() << endl;
outf.open(filename.str().c_str());
outf << nplayers << endl;
@@ -184,7 +150,7 @@ void write_mac_keys(const string& directory, int i, int nplayers, gfp macp, T ma
outf.close();
}
void read_keys(const string& directory, gfp& keyp, gf2n& key2, int nplayers)
inline void read_keys(const string& directory, gfp& keyp, gf2n& key2, int nplayers)
{
gfp sharep;
gf2n share2;
@@ -217,6 +183,3 @@ void read_keys(const string& directory, gfp& keyp, gf2n& key2, int nplayers)
}
std::cout << "Final MAC keys :\t p: " << keyp << "\n\t\t 2: " << key2 << std::endl;
}
template void write_mac_keys(const string& directory, int i, int nplayers, gfp macp, gf2n_short mac2);
template void write_mac_keys(const string& directory, int i, int nplayers, gfp macp, gf2n_long mac2);

View File

@@ -3,7 +3,7 @@
*
*/
#include "Secret.h"
#include "GC/Secret.h"
namespace GC
{

View File

@@ -45,6 +45,11 @@ public:
int get_i() { return i; }
};
namespace GC
{
template<class T> class Machine;
}
class CommonParty : public NodeUpdatable
{
protected:

View File

@@ -11,7 +11,7 @@
#include <fcntl.h>
#include <stdlib.h>
#include <valgrind/callgrind.h>
#include "Tools/callgrind.h"
#include "proto_utils.h"
#include "msg_types.h"

View File

@@ -229,7 +229,6 @@ public:
static T get_input(int from, GC::Processor<T>& processor, int n_bits)
{ return T::input(from, processor.get_input(n_bits), n_bits); }
// static void check_input(long long in, int n_bits) { (void)in; (void)n_bits; }
void input(party_id_t from, char value = -1) { (void)from; (void)value; }
void public_input(bool value) { (void)value; }
void random() {}

View File

@@ -17,6 +17,8 @@
#include "SpdzWire.h"
#include "Auth/fake-stuff.h"
#include "Auth/fake-stuff.hpp"
TrustedProgramParty* TrustedProgramParty::singleton = 0;

View File

@@ -13,6 +13,8 @@
#include "Math/Setup.h"
#include "Processor/Data_Files.h"
#include "Auth/fake-stuff.hpp"
#include <sstream>
#include <fstream>
#include <vector>
@@ -21,10 +23,10 @@ using namespace std;
string PREP_DATA_PREFIX;
template<class T>
void check_mult_triples(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF)
void check_mult_triples(const typename T::value_type& key,int N,vector<Sub_Data_Files<T>*>& dataF)
{
T a,b,c,mac,res;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
typename T::clear a,b,c,mac,res;
vector<T> Sa(N),Sb(N),Sc(N);
int n = 0;
try {
@@ -89,10 +91,10 @@ void check_tuple(const T& a, const T& b, int n, Dtype type)
}
template<class T>
void check_tuples(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF, Dtype type)
void check_tuples(const typename T::value_type& key,int N,vector<Sub_Data_Files<T>*>& dataF, Dtype type)
{
T a,b,c,mac,res;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
typename T::clear a,b,c,mac,res;
vector<T> Sa(N),Sb(N),Sc(N);
int n = 0;
try {
@@ -147,10 +149,10 @@ void check_bits(const typename T::value_type& key,int N,vector<Sub_Data_Files<T>
}
template<class T>
void check_inputs(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF)
void check_inputs(const typename T::value_type& key,int N,vector<Sub_Data_Files<T>*>& dataF)
{
T a, mac, x;
vector< Share<T> > Sa(N);
typename T::clear a, mac, x;
vector<T> Sa(N);
for (int player = 0; player < N; player++)
{
@@ -176,27 +178,27 @@ void check_inputs(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF)
}
template<class T>
vector<Sub_Data_Files<T>*> setup(int N, DataPositions& usage)
vector<Sub_Data_Files<T>*> setup(int N, DataPositions& usage, int thread_num = -1)
{
vector<Sub_Data_Files<T>*> dataF(N);
for (int i = 0; i < N; i++)
dataF[i] = new Sub_Data_Files<T>(i, N, PREP_DATA_PREFIX, usage);
dataF[i] = new Sub_Data_Files<T>(i, N, PREP_DATA_PREFIX, usage, thread_num);
return dataF;
}
template<class T>
void check(T key, int N, bool only_bits = false)
void check(typename T::value_type key, int N, bool only_bits = false)
{
DataPositions usage(N);
auto dataF = setup<Share<T>>(N, usage);
auto dataF = setup<T>(N, usage);
check_bits(key, N, dataF);
if (not only_bits)
{
check_mult_triples(key, N, dataF);
check_inputs(key, N, dataF);
check_tuples(key, N, dataF, DATA_SQUARE);
check_tuples(key, N, dataF, DATA_INVERSE);
check_inputs<T>(key, N, dataF);
check_tuples<T>(key, N, dataF, DATA_SQUARE);
check_tuples<T>(key, N, dataF, DATA_INVERSE);
}
}
@@ -304,13 +306,19 @@ int main(int argc, const char** argv)
cout << "--------------\n";
cout << "Final Keys :\t p: " << keyp << "\n\t\t 2: " << key2 << endl;
check(keyp, N);
check(key2, N);
check<sgfp>(keyp, N);
check<Share<gf2n>>(key2, N);
if (N == 3)
{
DataPositions pos(N);
auto dataF = setup<Rep3Share>(N, pos);
auto dataF = setup<Rep3Share<Integer>>(N, pos);
check_bits({}, N, dataF);
check<Rep3Share<gfp>>({}, N);
auto dataF2 = setup<GC::MaliciousRepSecret>(N, pos, 0);
check_mult_triples({}, N, dataF2);
check_bits({}, N, dataF2);
}
}

View File

@@ -89,6 +89,10 @@ class shrci(base.Instruction):
code = base.opcodes['SHRCI']
arg_format = ['cbw','cb','int']
class shlci(base.Instruction):
code = base.opcodes['SHLCI']
arg_format = ['cbw','cb','int']
class ldbits(base.Instruction):
code = opcodes['LDBITS']
arg_format = ['sbw','i','i']
@@ -186,3 +190,16 @@ class print_reg_plain(base.IOInstruction):
class print_reg_signed(base.IOInstruction):
code = opcodes['PRINTREGSIGNED']
arg_format = ['int','cb']
class print_float_plain(base.IOInstruction):
__slots__ = []
code = base.opcodes['PRINTFLOATPLAIN']
arg_format = ['cb', 'cb', 'cb', 'cb']
class cond_print_str(base.IOInstruction):
r""" Print a 4 character string. """
code = base.opcodes['CONDPRINTSTR']
arg_format = ['cb', 'int']
def __init__(self, cond, val):
super(cond_print_str, self).__init__(cond, self.str_to_int(val))

View File

@@ -155,11 +155,17 @@ class cbits(bits):
res = cbits(n=self.n-other)
inst.shrci(res, self, other)
return res
def __lshift__(self, other):
res = cbits(n=self.n+other)
inst.shlci(res, self, other)
return res
def print_reg(self, desc=''):
inst.print_reg(self, desc)
def print_reg_plain(self):
inst.print_reg_signed(self.n, self)
output = print_reg_plain
def print_if(self, string):
inst.cond_print_str(self, string)
def reveal(self):
return self
@@ -557,9 +563,18 @@ class sbitintvec(sbitvec):
assert(len(self.v) == len(other.v))
return self.from_vec(sbitint.bit_less_than(self.v, other.v))
class cbitfix(object):
def __init__(self, value):
self.v = value
def output(self):
bits = self.v.bit_decompose(self.k)
sign = bits[-1]
v = self.v + (sign << (self.k)) * -1
inst.print_float_plain(v, cbits(-self.f, n=32), cbits(0), cbits(0))
class sbitfix(_fix):
float_type = type(None)
clear_type = staticmethod(lambda x: x)
clear_type = cbitfix
@classmethod
def set_precision(cls, f, k=None):
super(cls, sbitfix).set_precision(f, k)

View File

@@ -26,6 +26,7 @@ def run(args, options, param=-1, merge_opens=True, emulate=True, \
VARS['program'] = prog
if options.binary:
VARS['sint'] = GC.types.sbitint.get_type(int(options.binary))
VARS['sfix'] = GC.types.sbitfix
comparison.set_variant(options)
print 'Compiling file', prog.infile

View File

@@ -443,7 +443,7 @@ class VectorArray(Vector):
def __len__(self):
return len(self.arrays[0])
class IntVectorArray(Array, Vector):
class IntVectorArray(Vector, Array):
def __init__(self, length):
Array.__init__(self, length, 's')

View File

@@ -123,7 +123,7 @@ def topological_sort(G, nbunch=None, pref=None):
yield i
if nbunch is None:
nbunch = range(len(G))
nbunch = reversed(range(len(G)))
for v in nbunch: # process all vertices in G
if v in explored:
continue

View File

@@ -856,15 +856,16 @@ class prep(base.Instruction):
@base.gf2n
@base.vectorize
class asm_input(base.IOInstruction):
class asm_input(base.VarArgsInstruction):
r""" Receive input from player $p$ and put in register $s_i$. """
__slots__ = []
code = base.opcodes['INPUT']
arg_format = ['sw', 'p']
arg_format = tools.cycle(['sw', 'p'])
field_type = 'modp'
def add_usage(self, req_node):
req_node.increment((self.field_type, 'input', self.args[1]), \
for player in self.args[1::2]:
req_node.increment((self.field_type, 'input', player), \
self.get_size())
def execute(self):
self.args[0].value = _python_input("Enter player %d's input:" % self.args[1]) % program.P
@@ -967,6 +968,14 @@ class print_char4(base.IOInstruction):
def __init__(self, val):
super(print_char4, self).__init__(self.str_to_int(val))
class cond_print_str(base.IOInstruction):
r""" Print a 4 character string. """
code = base.opcodes['CONDPRINTSTR']
arg_format = ['c', 'int']
def __init__(self, cond, val):
super(cond_print_str, self).__init__(cond, self.str_to_int(val))
@base.vectorize
class print_char_regint(base.IOInstruction):
r""" Print register $ci_i$ as a single character to stdout. """

View File

@@ -162,6 +162,7 @@ opcodes = dict(
PRINTFLOATPLAIN = 0xBC,
WRITEFILESHARE = 0xBD,
READFILESHARE = 0xBE,
CONDPRINTSTR = 0xBF,
GBITDEC = 0x184,
GBITCOM = 0x185,
# Secure socket

View File

@@ -1,7 +1,7 @@
from Compiler.types import cint,sint,cfix,sfix,sfloat,MPCThread,Array,MemValue,cgf2n,sgf2n,_number,_mem,_register,regint,Matrix,_types, cfloat
from Compiler.instructions import *
from Compiler.util import tuplify,untuplify
from Compiler import instructions,instructions_base,comparison,program
from Compiler import instructions,instructions_base,comparison,program,util
import inspect,math
import random
import collections
@@ -93,6 +93,16 @@ def print_ln(s='', *args):
print_str(s, *args)
print_char('\n')
def print_ln_if(cond, s):
if util.is_constant(cond):
if cond:
print_ln(s)
else:
s += '\n'
while s:
cond.print_if(s[:4])
s = s[4:]
def runtime_error(msg='', *args):
""" Print an error message and abort the runtime. """
print_str('User exception: ')

View File

@@ -67,7 +67,9 @@ class Program(object):
self.to_merge = [Compiler.instructions.asm_open_class, \
Compiler.instructions.gasm_open_class, \
Compiler.instructions.muls_class, \
Compiler.instructions.gmuls_class]
Compiler.instructions.gmuls_class, \
Compiler.instructions.asm_input_class, \
Compiler.instructions.gasm_input_class]
import Compiler.GC.instructions as gc
self.to_merge += [gc.ldmsdi, gc.stmsdi, gc.ldmsd, gc.stmsd, \
gc.stmsdci, gc.xors, gc.andrs, gc.ands, gc.inputb]
@@ -563,6 +565,8 @@ class Tape:
print 'Block requires', \
', '.join('%d %s' % (y, x.__name__) \
for x, y in merger.counter.items())
# free memory
merger = None
if options.dead_code_elimination:
block.instructions = filter(lambda x: x is not None, block.instructions)
if not (options.merge_opens and self.merge_opens):

View File

@@ -192,6 +192,8 @@ class _register(Tape.Register, _number):
return type(val)(cls.conv(v) for v in val)
except TypeError:
pass
except CompilerError:
pass
return cls(val)
@vectorized_classmethod
@@ -517,6 +519,9 @@ class cint(_clear, _int):
digestc(res, self, num_bytes)
return res
def print_if(self, string):
cond_print_str(self, string)
@@ -1941,7 +1946,12 @@ class cfix(_number):
raise TypeError('Incompatible fixed point types in division')
def print_plain(self):
sign = cint(self.v < 0)
if self.k > 64:
raise CompilerError('Printing of fixed-point numbers not ' +
'implemented for more than 64-bit precision')
tmp = regint()
convmodp(tmp, self.v, bitlength=self.k)
sign = cint(tmp < 0)
abs_v = sign.if_else(-self.v, self.v)
print_float_plain(cint(abs_v), cint(-self.f), \
cint(0), cint(sign))
@@ -1984,11 +1994,22 @@ class _fix(_number):
return cls(*res)
@classmethod
def load_sint(cls, v):
def from_sint(cls, other):
res = cls()
res.load_int(v)
res.load_int(cls.int_type.conv(other))
return res
@classmethod
def conv(cls, other):
if isinstance(other, cls):
return other
else:
try:
return cls.from_sint(other)
except (TypeError, CompilerError):
pass
return cls(other)
@vectorize_init
def __init__(self, _v=None, size=None):
self.size = get_global_vector_size()
@@ -2017,9 +2038,6 @@ class _fix(_number):
def load_int(self, v):
self.v = self.int_type(v) << self.f
def conv(self):
return self
def store_in_mem(self, address):
self.v.store_in_mem(address)
@@ -2028,7 +2046,7 @@ class _fix(_number):
@vectorize
def add(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (_fix, cfix)):
return type(self)(self.v + other.v)
elif isinstance(other, cfix.scalars):
@@ -2039,7 +2057,7 @@ class _fix(_number):
@vectorize
def mul(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, _fix):
val = self.v.TruncMul(other.v, self.k * 2, self.f, self.kappa)
return type(self)(val)
@@ -2054,7 +2072,7 @@ class _fix(_number):
@vectorize
def __sub__(self, other):
other = parse_type(other)
other = self.conv(other)
return self + (-other)
@vectorize
@@ -2066,7 +2084,7 @@ class _fix(_number):
@vectorize
def __eq__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (cfix, _fix)):
return self.v.equal(other.v, self.k, self.kappa)
else:
@@ -2074,7 +2092,7 @@ class _fix(_number):
@vectorize
def __le__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (cfix, _fix)):
return self.v.less_equal(other.v, self.k, self.kappa)
else:
@@ -2082,7 +2100,7 @@ class _fix(_number):
@vectorize
def __lt__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (cfix, _fix)):
return self.v.less_than(other.v, self.k, self.kappa)
else:
@@ -2090,7 +2108,7 @@ class _fix(_number):
@vectorize
def __ge__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (cfix, _fix)):
return self.v.greater_equal(other.v, self.k, self.kappa)
else:
@@ -2098,7 +2116,7 @@ class _fix(_number):
@vectorize
def __gt__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (cfix, _fix)):
return self.v.greater_than(other.v, self.k, self.kappa)
else:
@@ -2106,7 +2124,7 @@ class _fix(_number):
@vectorize
def __ne__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, (cfix, _fix)):
return self.v.not_equal(other.v, self.k, self.kappa)
else:
@@ -2114,7 +2132,7 @@ class _fix(_number):
@vectorize
def __div__(self, other):
other = parse_type(other)
other = self.conv(other)
if isinstance(other, _fix):
return type(self)(library.FPDiv(self.v, other.v, self.k, self.f, self.kappa))
elif isinstance(other, cfix):
@@ -2122,18 +2140,28 @@ class _fix(_number):
else:
raise TypeError('Incompatible fixed point types in division')
def __rdiv__(self, other):
return self.conv(other) / self
@vectorize
def compute_reciprocal(self):
return type(self)(library.FPDiv(cint(2) ** self.f, self.v, self.k, self.f, self.kappa, True))
def reveal(self):
val = self.v.reveal()
return self.clear_type(val)
res = self.clear_type(val)
res.f = self.f
res.k = self.k
return res
class sfix(_fix):
int_type = sint
clear_type = cfix
@classmethod
def conv(cls, other):
return parse_type(other)
# this is for 20 bit decimal precision
# with 40 bitlength of entire number
# these constants have been chosen for multiplications to fit in 128 bit prime field
@@ -2467,7 +2495,7 @@ class Array(object):
res.assign(tmp)
return res
def __init__(self, length, value_type, address=None):
def __init__(self, length, value_type, address=None, debug=None):
if value_type in _types:
value_type = _types[value_type]
self.address = address
@@ -2476,6 +2504,7 @@ class Array(object):
if address is None:
self.address = self._malloc()
self.address_cache = {}
self.debug = debug
def _malloc(self):
return program.malloc(self.length, self.value_type)
@@ -2492,6 +2521,9 @@ class Array(object):
(str(index), str(self.length)))
if (program.curr_block, index) not in self.address_cache:
self.address_cache[program.curr_block, index] = self.address + index
if self.debug:
library.print_ln_if(index >= self.length, 'OF:' + self.debug)
library.print_ln_if(self.address_cache[program.curr_block, index] >= program.allocated_mem[self.value_type.reg_type], 'AOF:' + self.debug)
return self.address_cache[program.curr_block, index]
def get_slice(self, index):
@@ -2589,25 +2621,37 @@ sgf2n.dynamic_array = Array
class SubMultiArray(object):
def __init__(self, sizes, value_type, address, index):
def __init__(self, sizes, value_type, address, index, debug=None):
self.sizes = sizes
self.value_type = value_type
self.address = address + index * reduce(operator.mul, self.sizes)
self.sub_cache = {}
self.debug = debug
if debug:
library.print_ln_if(self.address + reduce(operator.mul, self.sizes) > program.allocated_mem[self.value_type.reg_type], 'AOF%d:' % len(self.sizes) + self.debug)
def __getitem__(self, index):
if util.is_constant(index) and index >= self.sizes[0]:
raise StopIteration
key = program.curr_block, index
if key not in self.sub_cache:
if self.debug:
library.print_ln_if(index >= self.sizes[0], \
'OF%d:' % len(self.sizes) + self.debug)
if len(self.sizes) == 2:
self.sub_cache[key] = \
Array(self.sizes[1], self.value_type, \
self.address + index * self.sizes[1])
self.address + index * self.sizes[1], \
debug=self.debug)
else:
self.sub_cache[key] = \
SubMultiArray(self.sizes[1:], self.value_type, \
self.address, index)
self.address, index, debug=self.debug)
return self.sub_cache[key]
def __len__(self):
return self.sizes[0]
def assign_all(self, value):
@library.for_range(self.sizes[0])
def f(i):
@@ -2615,16 +2659,17 @@ class SubMultiArray(object):
return self
class MultiArray(SubMultiArray):
def __init__(self, sizes, value_type):
def __init__(self, sizes, value_type, debug=None):
self.array = Array(reduce(operator.mul, sizes), \
value_type)
SubMultiArray.__init__(self, sizes, value_type, self.array.address, 0)
SubMultiArray.__init__(self, sizes, value_type, self.array.address, 0, \
debug=debug)
if len(sizes) < 2:
raise CompilerError('Use Array')
class Matrix(MultiArray):
def __init__(self, rows, columns, value_type):
MultiArray.__init__(self, [rows, columns], value_type)
def __init__(self, rows, columns, value_type, debug=None):
MultiArray.__init__(self, [rows, columns], value_type, debug=debug)
def __mul__(self, other):
assert isinstance(other, Array)

View File

@@ -7,6 +7,8 @@
#include "Tools/benchmarking.h"
#include "Auth/fake-stuff.h"
#include "Auth/fake-stuff.hpp"
PairwiseMachine::PairwiseMachine(int argc, const char** argv) :
MachineBase(argc, argv), P(N, 0xffff << 16),
other_pks(N.num_players(), {setup_p.params, 0}),

View File

@@ -5,6 +5,7 @@
#include "Math/Setup.h"
#include "Auth/fake-stuff.h"
#include "Exceptions/Exceptions.h"
#include "GC/MaliciousRepSecret.h"
#include "Math/Setup.h"
#include "Processor/Data_Files.h"
@@ -12,6 +13,8 @@
#include "Tools/ezOptionParser.h"
#include "Tools/benchmarking.h"
#include "Auth/fake-stuff.hpp"
#include <sstream>
#include <fstream>
using namespace std;
@@ -24,18 +27,20 @@ string prep_data_prefix;
* str = "2" or "p"
*/
template<class T>
void make_mult_triples(const T& key,int N,int ntrip,const string& str,bool zero)
void make_mult_triples(const typename T::value_type& key, int N, int ntrip,
bool zero, int thread_num = -1)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a,b,c;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
typename T::value_type a,b,c;
vector<T> Sa(N),Sb(N),Sc(N);
/* Generate Triples */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Triples-" << str << "-P" << i;
filename << prep_data_prefix << "Triples-" << T::type_short() << "-P" << i
<< Sub_Data_Files<T>::get_suffix(thread_num);
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
@@ -108,14 +113,14 @@ void make_bit_triples(const gf2n& key,int N,int ntrip,Dtype dtype,bool zero)
* str = "2" or "p"
*/
template<class T>
void make_square_tuples(const T& key,int N,int ntrip,const string& str,bool zero)
void make_square_tuples(const typename T::value_type& key,int N,int ntrip,const string& str,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a,c;
vector<Share<T> > Sa(N),Sc(N);
typename T::clear a,c;
vector<T> Sa(N),Sc(N);
/* Generate Squares */
for (int i=0; i<N; i++)
{ stringstream filename;
@@ -145,7 +150,8 @@ void make_square_tuples(const T& key,int N,int ntrip,const string& str,bool zero
* ntrip = Number bits needed
*/
template<class T>
void make_bits(const typename T::value_type& key,int N,int ntrip,bool zero)
void make_bits(const typename T::value_type& key, int N, int ntrip, bool zero,
int thread_num = -1)
{
PRNG G;
G.ReSeed();
@@ -156,7 +162,8 @@ void make_bits(const typename T::value_type& key,int N,int ntrip,bool zero)
/* Generate Bits */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Bits-" << T::type_char() << "-P" << i;
filename << prep_data_prefix << "Bits-" << T::type_short() << "-P" << i
<< Sub_Data_Files<T>::get_suffix(thread_num);
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
@@ -180,14 +187,14 @@ void make_bits(const typename T::value_type& key,int N,int ntrip,bool zero)
*
*/
template<class T>
void make_inputs(const T& key,int N,int ntrip,const string& str,bool zero)
void make_inputs(const typename T::value_type& key,int N,int ntrip,const string& str,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a;
vector<Share<T> > Sa(N);
typename T::clear a;
vector<T> Sa(N);
/* Generate Inputs */
for (int player=0; player<N; player++)
{ for (int i=0; i<N; i++)
@@ -220,18 +227,18 @@ void make_inputs(const T& key,int N,int ntrip,const string& str,bool zero)
* str = "2" or "p"
*/
template<class T>
void make_inverse(const T& key,int N,int ntrip,bool zero)
void make_inverse(const typename T::value_type& key,int N,int ntrip,bool zero)
{
PRNG G;
G.ReSeed();
ofstream* outf=new ofstream[N];
T a,b;
vector<Share<T> > Sa(N),Sb(N);
typename T::clear a,b;
vector<T> Sa(N),Sb(N);
/* Generate Triples */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Inverses-" << T::type_char() << "-P" << i;
filename << prep_data_prefix << "Inverses-" << T::type_short() << "-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
@@ -260,14 +267,14 @@ void make_inverse(const T& key,int N,int ntrip,bool zero)
template<class T>
void make_PreMulC(const T& key, int N, int ntrip, bool zero)
void make_PreMulC(const typename T::value_type& key, int N, int ntrip, bool zero)
{
stringstream ss;
ss << prep_data_prefix << "PreMulC-" << T::type_char();
ss << prep_data_prefix << "PreMulC-" << T::type_short();
Files<T> files(N, key, ss.str());
PRNG G;
G.ReSeed();
T a, b, c;
typename T::clear a, b, c;
c = 1;
for (int i=0; i<ntrip; i++)
{
@@ -287,6 +294,17 @@ void make_PreMulC(const T& key, int N, int ntrip, bool zero)
}
}
template<class T>
void make_basic(const typename T::value_type& key, int nplayers, int nitems, bool zero)
{
make_mult_triples<T>(key, nplayers, nitems, zero);
make_bits<T>(key, nplayers, nitems, zero);
make_square_tuples<T>(key, nplayers, nitems, T::type_short(), zero);
make_inputs<T>(key, nplayers, nitems, T::type_short(), zero);
make_inverse<T>(key, nplayers, nitems, zero);
make_PreMulC<T>(key, nplayers, nitems, zero);
}
int main(int argc, const char** argv)
{
insecure("preprocessing");
@@ -535,22 +553,31 @@ int main(int argc, const char** argv)
cout << "--------------\n";
cout << "Final Keys :\t p: " << keyp << "\n\t\t 2: " << key2 << endl;
make_mult_triples(key2,nplayers,ntrip2,"2",zero);
make_mult_triples(keyp,nplayers,ntripp,"p",zero);
typedef Share<gf2n> sgf2n;
make_mult_triples<sgf2n>(key2,nplayers,ntrip2,zero);
make_mult_triples<sgfp>(keyp,nplayers,ntripp,zero);
make_bits<Share<gf2n>>(key2,nplayers,nbits2,zero);
make_bits<Share<gfp>>(keyp,nplayers,nbitsp,zero);
make_square_tuples(key2,nplayers,nsqr2,"2",zero);
make_square_tuples(keyp,nplayers,nsqrp,"p",zero);
make_inputs(key2,nplayers,ninp2,"2",zero);
make_inputs(keyp,nplayers,ninpp,"p",zero);
make_inverse(key2,nplayers,ninv,zero);
make_inverse(keyp,nplayers,ninv,zero);
make_square_tuples<sgf2n>(key2,nplayers,nsqr2,"2",zero);
make_square_tuples<sgfp>(keyp,nplayers,nsqrp,"p",zero);
make_inputs<sgf2n>(key2,nplayers,ninp2,"2",zero);
make_inputs<sgfp>(keyp,nplayers,ninpp,"p",zero);
make_inverse<sgf2n>(key2,nplayers,ninv,zero);
make_inverse<sgfp>(keyp,nplayers,ninv,zero);
make_bit_triples(key2,nplayers,nbittrip,DATA_BITTRIPLE,zero);
make_bit_triples(key2,nplayers,nbitgf2ntrip,DATA_BITGF2NTRIPLE,zero);
make_PreMulC(key2,nplayers,ninv,zero);
make_PreMulC(keyp,nplayers,ninv,zero);
make_PreMulC<sgf2n>(key2,nplayers,ninv,zero);
make_PreMulC<sgfp>(keyp,nplayers,ninv,zero);
// replicated secret sharing only for three parties
if (nplayers == 3)
make_bits<Rep3Share>({}, nplayers, nbitsp, zero);
{
make_bits<Rep3Share<Integer>>({}, nplayers, nbitsp, zero);
make_basic<Rep3Share<gfp>>({}, nplayers, default_num, zero);
make_basic<Rep3Share<gf2n>>({}, nplayers, default_num, zero);
make_mult_triples<GC::MaliciousRepSecret>({}, nplayers, ntrip2, zero);
make_bits<GC::MaliciousRepSecret>({}, nplayers, nbits2, zero);
}
}

View File

@@ -78,6 +78,21 @@ public:
}
};
class InputArgList : public ArgList<InputArgs>
{
public:
InputArgList(const vector<int>& args) :
ArgList<InputArgs>(args)
{
}
int n_inputs_from(int from)
{
int res = 0;
for (auto x : *this)
res += x.from == from;
return res;
}
};
#endif /* GC_ARGTUPLES_H_ */

View File

@@ -10,7 +10,8 @@
#include "GC/Memory.h"
#include "GC/Access.h"
#include "Auth/MAC_Check.h"
#include "Math/gf2nlong.h"
#include "Processor/DummyProtocol.h"
#include <random>
@@ -30,7 +31,7 @@ public:
typedef FakeSecret DynamicType;
// dummy
typedef MAC_Check_Base<FakeSecret> MC;
typedef DummyMC MC;
typedef DummyProtocol Protocol;
static string type_string() { return "fake secret"; }

View File

@@ -10,8 +10,6 @@
#include <iostream>
using namespace std;
#include "GC/Processor.h"
#include "Processor/Instruction.h"
namespace GC
@@ -27,6 +25,7 @@ enum RegType {
NONE
};
template<class T> class Processor;
template <class T>
class Instruction : public ::BaseInstruction
@@ -49,10 +48,10 @@ public:
int get_reg_type() const;
// Returns the maximal register used
int get_max_reg(int reg_type) const;
unsigned get_max_reg(int reg_type) const;
// Returns the memory size used if applicable and known
int get_mem(RegType reg_type) const;
unsigned get_mem(RegType reg_type) const;
// Execute this instruction
bool exe(Processor<T>& processor) const { return code(*this, processor); }

View File

@@ -6,6 +6,8 @@
#include <algorithm>
#include "GC/Instruction.h"
#include "GC/Processor.h"
#ifdef MAX_INLINE
#include "GC/Secret_inline.h"
#endif
@@ -73,7 +75,7 @@ int Instruction<T>::get_reg_type() const
}
template<class T>
int GC::Instruction<T>::get_max_reg(int reg_type) const
unsigned GC::Instruction<T>::get_max_reg(int reg_type) const
{
int skip;
int offset = 0;
@@ -101,17 +103,17 @@ int GC::Instruction<T>::get_max_reg(int reg_type) const
return BaseInstruction::get_max_reg(reg_type);
}
int m = 0;
unsigned m = 0;
if (reg_type == SBIT)
for (size_t i = offset; i < start.size(); i += skip)
m = max(m, start[i] + 1);
m = max(m, (unsigned)start[i] + 1);
return m;
}
template <class T>
int Instruction<T>::get_mem(RegType reg_type) const
unsigned Instruction<T>::get_mem(RegType reg_type) const
{
int m = n + 1;
unsigned m = n + 1;
switch (opcode)
{
case LDMSD:
@@ -119,7 +121,7 @@ int Instruction<T>::get_mem(RegType reg_type) const
{
m = 0;
for (size_t i = 0; i < start.size() / 3; i++)
m = max(m, start[3*i+1] + 1);
m = max(m, (unsigned)start[3*i+1] + 1);
return m;
}
break;
@@ -128,7 +130,7 @@ int Instruction<T>::get_mem(RegType reg_type) const
{
m = 0;
for (size_t i = 0; i < start.size() / 2; i++)
m = max(m, start[2*i+1] + 1);
m = max(m, (unsigned)start[2*i+1] + 1);
return m;
}
break;
@@ -232,6 +234,8 @@ void Instruction<T>::parse(istream& s, int pos)
default:
ostringstream os;
os << "Code not defined for instruction " << showbase << hex << opcode << dec;
os << "This virtual machine executes binary circuits only." << endl;
os << "Try compiling with '-B' or use only sbit* types." << endl;
throw Invalid_Instruction(os.str());
break;
}

View File

@@ -3,24 +3,34 @@
*
*/
#include "MaliciousRepSecret.h"
#include "Auth/ReplicatedMC.h"
#include "Auth/MaliciousRepMC.h"
#include "Instruction.hpp"
#include "Machine.hpp"
#include "Processor.hpp"
#include "Program.hpp"
#include "Thread.hpp"
#include "ThreadMaster.hpp"
#include "Auth/MaliciousRepMC.hpp"
namespace GC
{
template class Machine<FakeSecret>;
template class Machine<ReplicatedSecret>;
extern template class ReplicatedSecret<SemiHonestRepSecret>;
extern template class ReplicatedSecret<MaliciousRepSecret>;
template class Processor<FakeSecret>;
template class Processor<ReplicatedSecret>;
#define GC_MACHINE(T) \
template class Instruction<T>; \
template class Machine<T>; \
template class Processor<T>; \
template class Program<T>; \
template class Thread<T>; \
template class ThreadMaster<T>; \
template class Thread<FakeSecret>;
template class Thread<ReplicatedSecret>;
template class ThreadMaster<FakeSecret>;
template class ThreadMaster<ReplicatedSecret>;
GC_MACHINE(FakeSecret);
GC_MACHINE(SemiHonestRepSecret);
GC_MACHINE(MaliciousRepSecret)
} /* namespace GC */

View File

@@ -10,7 +10,7 @@
#include "GC/Clear.h"
#include "GC/Memory.h"
#include "Processor/Machine.h"
#include "Processor/BaseMachine.h"
#include <vector>
using namespace std;
@@ -32,6 +32,7 @@ public:
vector<Program<T> > progs;
bool use_encryption;
bool more_comm_less_comp;
Machine(Memory<typename T::DynamicType>& MD);
~Machine();

View File

@@ -17,6 +17,7 @@ template <class T>
Machine<T>::Machine(Memory<typename T::DynamicType>& dynamic_memory) : MD(dynamic_memory)
{
use_encryption = false;
more_comm_less_comp = false;
start_timer();
}

34
GC/MaliciousRepSecret.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* MaliciousRepSecret.h
*
*/
#ifndef GC_MALICIOUSREPSECRET_H_
#define GC_MALICIOUSREPSECRET_H_
#include "ReplicatedSecret.h"
template<class T> class MaliciousRepMC;
namespace GC
{
class MaliciousRepThread;
class MaliciousRepSecret : public ReplicatedSecret<MaliciousRepSecret>
{
typedef ReplicatedSecret<MaliciousRepSecret> super;
public:
typedef MaliciousRepSecret DynamicType;
typedef MaliciousRepMC<MaliciousRepSecret> MC;
MaliciousRepSecret() {}
template<class T>
MaliciousRepSecret(const T& other) : super(other) {}
};
}
#endif /* GC_MALICIOUSREPSECRET_H_ */

94
GC/MaliciousRepThread.cpp Normal file
View File

@@ -0,0 +1,94 @@
/*
* MalicousRepParty.cpp
*
*/
#include "Auth/MaliciousRepMC.h"
#include "MaliciousRepThread.h"
#include "Math/Setup.h"
#include "Auth/MaliciousRepMC.hpp"
namespace GC
{
thread_local MaliciousRepThread* MaliciousRepThread::singleton = 0;
MaliciousRepThread::MaliciousRepThread(int i,
ThreadMaster<MaliciousRepSecret>& master) :
Thread<MaliciousRepSecret>(i, master), DataF(N.my_num(),
N.num_players(),
get_prep_dir(N.num_players(), 128, gf2n::default_degree()),
usage, i)
{
}
MaliciousRepMC<MaliciousRepSecret>* MaliciousRepThread::new_mc()
{
if (machine.more_comm_less_comp)
return new CommMaliciousRepMC<MaliciousRepSecret>;
else
return new HashMaliciousRepMC<MaliciousRepSecret>;
}
void MaliciousRepThread::pre_run()
{
if (singleton)
throw runtime_error("there can only be one");
singleton = this;
}
void MaliciousRepThread::post_run()
{
#ifndef INSECURE
cerr << "Removing used pre-processed data" << endl;
DataF.prune();
#endif
}
void MaliciousRepThread::and_(Processor<MaliciousRepSecret>& processor,
const vector<int>& args, bool repeat)
{
assert(P->num_players() == 3);
os.resize(2);
for (auto& o : os)
o.reset_write_head();
processor.check_args(args, 4);
shares.clear();
triples.clear();
for (size_t i = 0; i < args.size(); i += 4)
{
int n_bits = args[i];
int left = args[i + 2];
int right = args[i + 3];
triples.push_back({0});
DataF.get(DATA_TRIPLE, triples.back().data());
shares.push_back((processor.S[left] - triples.back()[0]).mask(n_bits));
MaliciousRepSecret y_ext;
if (repeat)
y_ext = processor.S[right].extend_bit();
else
y_ext = processor.S[right];
shares.push_back((y_ext - triples.back()[1]).mask(n_bits));
}
MC->POpen_Begin(opened, shares, *P);
MC->POpen_End(opened, shares, *P);
auto it = opened.begin();
for (size_t i = 0; i < args.size(); i += 4)
{
int n_bits = args[i];
int out = args[i + 1];
MaliciousRepSecret tmp = triples[i / 4][2];
BitVec masked[2];
for (int k = 0; k < 2; k++)
{
masked[k] = *it++;
tmp += triples[i / 4][1 - k] & masked[k];
}
processor.S[out] = (tmp + (masked[0] & masked[1])).mask(n_bits);
}
}
} /* namespace GC */

53
GC/MaliciousRepThread.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* MalicousRepParty.h
*
*/
#ifndef GC_MALICIOUSREPTHREAD_H_
#define GC_MALICIOUSREPTHREAD_H_
#include "Thread.h"
#include "MaliciousRepSecret.h"
#include "Processor/Data_Files.h"
#include <array>
namespace GC
{
class MaliciousRepThread : public Thread<MaliciousRepSecret>
{
static thread_local MaliciousRepThread* singleton;
vector<MaliciousRepSecret> shares;
vector<BitVec> opened;
vector<array<MaliciousRepSecret, 3>> triples;
public:
static MaliciousRepThread& s();
DataPositions usage;
Sub_Data_Files<MaliciousRepSecret> DataF;
MaliciousRepThread(int i, ThreadMaster<MaliciousRepSecret>& master);
virtual ~MaliciousRepThread() {}
MaliciousRepSecret::MC* new_mc();
void pre_run();
void post_run();
void and_(Processor<MaliciousRepSecret>& processor, const vector<int>& args, bool repeat);
};
inline MaliciousRepThread& MaliciousRepThread::s()
{
if (singleton)
return *singleton;
else
throw runtime_error("no singleton");
}
} /* namespace GC */
#endif /* GC_MALICIOUSREPTHREAD_H_ */

View File

@@ -14,6 +14,7 @@ using namespace std;
#include "Exceptions/Exceptions.h"
#include "Clear.h"
#include "config.h"
namespace GC
{
@@ -41,7 +42,7 @@ inline void Memory<T>::check_index(Integer index) const
if (i >= vector<T>::size())
{
stringstream ss;
ss << "Memory overflow: " << i << "/" << vector<T>::size();
ss << T::type_string() << " memory overflow: " << i << "/" << vector<T>::size();
throw Processor_Error(ss.str());
}
#endif
@@ -69,7 +70,7 @@ template <class T>
inline void Memory<T>::resize(size_t size, const char* name)
{
if (size > 1000)
cout << "Resizing " << T::type_string() << " " << name << " to " << size << endl;
cerr << "Resizing " << T::type_string() << " " << name << " to " << size << endl;
vector<T>::resize(size);
}

View File

@@ -13,19 +13,27 @@ using namespace std;
#include "GC/Machine.h"
#include "Math/Integer.h"
#include "Processor/Processor.h"
#include "Processor/ProcessorBase.h"
namespace GC
{
template <class T> class Program;
class ExecutionStats : public map<int, size_t>
{
public:
ExecutionStats& operator+=(const ExecutionStats& other)
{
for (auto it : other)
(*this)[it.first] += it.second;
return *this;
}
};
template <class T>
class Processor : public ::ProcessorBase
{
ifstream input_file;
string input_filename;
public:
static int check_args(const vector<int>& args, int n);
@@ -43,14 +51,15 @@ public:
Memory<Clear> C;
Memory<Integer> I;
ExecutionStats stats;
Processor(Machine<T>& machine);
~Processor();
void reset(const Program<T>& program, int arg);
void reset(const Program<T>& program);
void open_input_file(const string& name);
long long get_input(int n_bits);
long long get_input(int n_bits, bool interactive = false);
void bitcoms(T& x, const vector<int>& regs) { x.bitcom(S, regs); }
void bitdecs(const vector<int>& regs, const T& x) { x.bitdec(S, regs); }
@@ -77,6 +86,7 @@ public:
void print_reg_signed(unsigned n_bits, Clear& value);
void print_chr(int n);
void print_str(int n);
void print_float(const vector<int>& args);
};
template <class T>

View File

@@ -47,22 +47,9 @@ void Processor<T>::reset(const Program<T>& program)
}
template<class T>
void GC::Processor<T>::open_input_file(const string& name)
inline long long GC::Processor<T>::get_input(int n_bits, bool interactive)
{
cout << "opening " << name << endl;
input_file.open(name);
input_filename = name;
}
template<class T>
inline long long GC::Processor<T>::get_input(int n_bits)
{
long long res;
input_file >> res;
if (input_file.eof())
throw IO_Error("not enough inputs in " + input_filename);
if (input_file.fail())
throw IO_Error("cannot read from " + input_filename);
long long res = ProcessorBase::get_input(interactive);
check_input(res, n_bits);
return res;
}
@@ -231,4 +218,10 @@ void Processor<T>::print_str(int n)
T::out << string((char*)&n,sizeof(n)) << flush;
}
template <class T>
void Processor<T>::print_float(const vector<int>& args)
{
T::out << bigint::get_float(C[args[0]], C[args[1]], C[args[2]], C[args[3]]) << flush;
}
} /* namespace GC */

View File

@@ -1,18 +0,0 @@
/*
* Program.cpp
*
*/
#include "Instruction.hpp"
#include "Program.hpp"
namespace GC
{
template class Instruction<FakeSecret>;
template class Instruction<ReplicatedSecret>;
template class Program<FakeSecret>;
template class Program<ReplicatedSecret>;
} /* namespace GC */

View File

@@ -29,10 +29,10 @@ class Program
int offline_data_used;
// Maximal register used
int max_reg[MAX_REG_TYPE];
unsigned max_reg[MAX_REG_TYPE];
// Memory size used directly
int max_mem[MAX_REG_TYPE];
unsigned max_mem[MAX_REG_TYPE];
// True if program contains variable-sized loop
bool unknown_usage;
@@ -53,10 +53,10 @@ class Program
bool usage_unknown() const { return unknown_usage; }
int num_reg(RegType reg_type) const
unsigned num_reg(RegType reg_type) const
{ return max_reg[reg_type]; }
int direct_mem(RegType reg_type) const
unsigned direct_mem(RegType reg_type) const
{ return max_mem[reg_type]; }
// Execute this program, updateing the processor and memory

View File

@@ -7,8 +7,9 @@
#include "Secret.h"
#include "ReplicatedSecret.h"
#include "config.h"
#include <valgrind/callgrind.h>
#include "Tools/callgrind.h"
#ifdef MAX_INLINE
#include "Instruction_inline.h"
@@ -118,6 +119,9 @@ BreakType Program<T>::execute(Processor<T>& Proc, int PC) const
Proc.time = time;
return DONE_BREAK;
}
#ifdef COUNT_INSTRUCTIONS
Proc.stats[p[Proc.PC].get_opcode()]++;
#endif
p[Proc.PC++].execute(Proc);
time++;
#ifdef DEBUG_COMPLEXITY

View File

@@ -5,6 +5,7 @@
#include "ReplicatedParty.h"
#include "Thread.h"
#include "MaliciousRepThread.h"
#include "Networking/Server.h"
#include "Tools/ezOptionParser.h"
#include "Tools/benchmarking.h"
@@ -12,9 +13,10 @@
namespace GC
{
ReplicatedParty::ReplicatedParty(int argc, const char** argv)
template<class T>
ReplicatedParty<T>::ReplicatedParty(int argc, const char** argv) :
ThreadMaster<T>(online_opts), online_opts(opt, argc, argv)
{
ez::ezOptionParser opt;
opt.add(
"", // Default.
1, // Required?
@@ -51,11 +53,20 @@ ReplicatedParty::ReplicatedParty(int argc, const char** argv)
"-u", // Flag token.
"--unencrypted" // Flag token.
);
opt.add(
"", // Default.
0, // Required?
0, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Check opening by communication instead of hashing.", // Help description.
"-c", // Flag token.
"--communication" // Flag token.
);
opt.parse(argc, argv);
opt.syntax = "./replicated-bin-party.x [OPTIONS] <progname>";
if (opt.lastArgs.size() == 1)
{
progname = *opt.lastArgs[0];
this->progname = *opt.lastArgs[0];
}
else
{
@@ -71,20 +82,52 @@ ReplicatedParty::ReplicatedParty(int argc, const char** argv)
opt.get("-p")->getInt(my_num);
opt.get("-pn")->getInt(pnb);
opt.get("-h")->getString(hostname);
machine.use_encryption = not opt.get("-u")->isSet;
this->machine.use_encryption = not opt.get("-u")->isSet;
this->machine.more_comm_less_comp = opt.get("-c")->isSet;
if (my_num != 0)
ReplicatedSecret::out.activate(false);
T::out.activate(my_num == 0 or online_opts.interactive);
if (not machine.use_encryption)
if (not this->machine.use_encryption)
insecure("unencrypted communication");
Server* server = Server::start_networking(N, my_num, 3, hostname, pnb);
Server* server = Server::start_networking(this->N, my_num, 3, hostname, pnb);
run();
this->run();
if (server)
delete server;
}
template<>
Thread<SemiHonestRepSecret>* ReplicatedParty<SemiHonestRepSecret>::new_thread(int i)
{
return ThreadMaster<SemiHonestRepSecret>::new_thread(i);
}
template<>
Thread<MaliciousRepSecret>* ReplicatedParty<MaliciousRepSecret>::new_thread(int i)
{
return new MaliciousRepThread(i, *this);
}
template<>
void ReplicatedParty<SemiHonestRepSecret>::post_run()
{
}
template<>
void ReplicatedParty<MaliciousRepSecret>::post_run()
{
DataPositions usage;
for (auto thread : threads)
usage.increase(((MaliciousRepThread*)thread)->usage);
usage.print_cost();
}
extern template class ReplicatedSecret<SemiHonestRepSecret>;
extern template class ReplicatedSecret<MaliciousRepSecret>;
template class ReplicatedParty<SemiHonestRepSecret>;
template class ReplicatedParty<MaliciousRepSecret>;
}

View File

@@ -7,6 +7,7 @@
#define GC_REPLICATEDPARTY_H_
#include "Auth/ReplicatedMC.h"
#include "Auth/MaliciousRepMC.h"
#include "ReplicatedSecret.h"
#include "Processor.h"
#include "Program.h"
@@ -16,17 +17,26 @@
namespace GC
{
class ReplicatedParty : public ThreadMaster<ReplicatedSecret>
template<class T>
class ReplicatedParty : public ThreadMaster<T>
{
ez::ezOptionParser opt;
OnlineOptions online_opts;
public:
static Thread<ReplicatedSecret>& s();
static Thread<T>& s();
ReplicatedParty(int argc, const char** argv);
Thread<T>* new_thread(int i);
void post_run();
};
inline Thread<ReplicatedSecret>& ReplicatedParty::s()
template<class T>
inline Thread<T>& ReplicatedParty<T>::s()
{
return Thread<ReplicatedSecret>::s();
return Thread<T>::s();
}
}

View File

@@ -5,67 +5,85 @@
#include "ReplicatedSecret.h"
#include "ReplicatedParty.h"
#include "MaliciousRepSecret.h"
#include "Auth/MaliciousRepMC.h"
#include "MaliciousRepThread.h"
#include "Thread.h"
#include "square64.h"
#include "Math/Share.h"
#include "Auth/ReplicatedMC.hpp"
namespace GC
{
int ReplicatedSecret::default_length = 8 * sizeof(ReplicatedSecret::value_type);
template<class U>
int ReplicatedSecret<U>::default_length = 8 * sizeof(ReplicatedSecret<U>::value_type);
SwitchableOutput ReplicatedSecret::out;
template<class U>
SwitchableOutput ReplicatedSecret<U>::out;
void ReplicatedSecret::load(int n, const Integer& x)
template<class U>
void ReplicatedSecret<U>::load(int n, const Integer& x)
{
if ((size_t)n < 8 * sizeof(x) and abs(x.get()) >= (1LL << n))
throw out_of_range("public value too long");
*this = x;
}
void ReplicatedSecret::bitcom(Memory<ReplicatedSecret>& S, const vector<int>& regs)
template<class U>
void ReplicatedSecret<U>::bitcom(Memory<U>& S, const vector<int>& regs)
{
*this = 0;
for (unsigned int i = 0; i < regs.size(); i++)
*this ^= (S[regs[i]] << i);
}
void ReplicatedSecret::bitdec(Memory<ReplicatedSecret>& S, const vector<int>& regs) const
template<class U>
void ReplicatedSecret<U>::bitdec(Memory<U>& S, const vector<int>& regs) const
{
for (unsigned int i = 0; i < regs.size(); i++)
S[regs[i]] = (*this >> i) & 1;
}
void ReplicatedSecret::load(vector<ReadAccess<ReplicatedSecret> >& accesses,
const Memory<ReplicatedSecret>& mem)
template<class U>
void ReplicatedSecret<U>::load(vector<ReadAccess<U> >& accesses,
const Memory<U>& mem)
{
for (auto access : accesses)
access.dest = mem[access.address];
}
void ReplicatedSecret::store(Memory<ReplicatedSecret>& mem,
vector<WriteAccess<ReplicatedSecret> >& accesses)
template<class U>
void ReplicatedSecret<U>::store(Memory<U>& mem,
vector<WriteAccess<U> >& accesses)
{
for (auto access : accesses)
mem[access.address] = access.source;
}
void ReplicatedSecret::store_clear_in_dynamic(Memory<DynamicType>& mem,
template<class U>
void ReplicatedSecret<U>::store_clear_in_dynamic(Memory<U>& mem,
const vector<ClearWriteAccess>& accesses)
{
for (auto access : accesses)
mem[access.address] = access.value;
}
void ReplicatedSecret::inputb(Processor<ReplicatedSecret>& processor,
template<class U>
void ReplicatedSecret<U>::inputb(Processor<U>& processor,
const vector<int>& args)
{
auto& party = ReplicatedParty::s();
auto& party = ReplicatedParty<U>::s();
party.os.resize(2);
for (auto& o : party.os)
o.reset_write_head();
processor.check_args(args, 3);
InputArgList a(args);
bool interactive = party.n_interactive_inputs_from_me(a) > 0;
for (size_t i = 0; i < args.size(); i += 3)
{
int from = args[i];
@@ -73,12 +91,15 @@ void ReplicatedSecret::inputb(Processor<ReplicatedSecret>& processor,
if (from == party.P->my_num())
{
auto& res = processor.S[args[i + 2]];
res.prepare_input(party.os, processor.get_input(n_bits), n_bits, party.secure_prng);
res.prepare_input(party.os, processor.get_input(n_bits, interactive), n_bits, party.secure_prng);
}
}
party.P->send_relative(party.os);
party.P->receive_relative(party.os);
if (interactive)
cout << "Thank you" << endl;
for (int i = 0; i < 2; i++)
party.P->pass_around(party.os[i], i + 1);
for (size_t i = 0; i < args.size(); i += 3)
{
@@ -87,17 +108,18 @@ void ReplicatedSecret::inputb(Processor<ReplicatedSecret>& processor,
if (from != party.P->my_num())
{
auto& res = processor.S[args[i + 2]];
res.finalize_input(party, party.os[party.P->get_offset(from) == 2], from, n_bits);
res.finalize_input(party, party.os[party.P->get_offset(from) == 1], from, n_bits);
}
}
}
ReplicatedSecret ReplicatedSecret::input(int from, Processor<ReplicatedSecret>& processor, int n_bits)
template<class U>
U ReplicatedSecret<U>::input(int from, Processor<U>& processor, int n_bits)
{
// BMR stuff counts from 1
from--;
auto& party = ReplicatedParty::s();
ReplicatedSecret res;
auto& party = ReplicatedParty<U>::s();
U res;
party.os.resize(2);
for (auto& o : party.os)
o.reset_write_head();
@@ -114,7 +136,8 @@ ReplicatedSecret ReplicatedSecret::input(int from, Processor<ReplicatedSecret>&
return res;
}
void ReplicatedSecret::prepare_input(vector<octetStream>& os, long input, int n_bits, PRNG& secure_prng)
template<class U>
void ReplicatedSecret<U>::prepare_input(vector<octetStream>& os, long input, int n_bits, PRNG& secure_prng)
{
randomize_to_sum(input, secure_prng);
*this &= get_mask(n_bits);
@@ -122,36 +145,18 @@ void ReplicatedSecret::prepare_input(vector<octetStream>& os, long input, int n_
BitVec(get_mask(n_bits) & (*this)[i]).pack(os[i], n_bits);
}
void ReplicatedSecret::finalize_input(Thread<ReplicatedSecret>& party, octetStream& o, int from, int n_bits)
template<class U>
void ReplicatedSecret<U>::finalize_input(Thread<U>& party, octetStream& o, int from, int n_bits)
{
int j = party.P->get_offset(from) == 2;
(*this)[j] = BitVec::unpack_new(o, n_bits);
(*this)[1 - j] = 0;
}
void ReplicatedSecret::and_(Processor<ReplicatedSecret>& processor,
const vector<int>& args, bool repeat)
{
auto& party = ReplicatedParty::s();
assert(party.P->num_players() == 3);
vector<octetStream>& os = party.os;
os.resize(2);
for (auto& o : os)
o.reset_write_head();
processor.check_args(args, 4);
for (size_t i = 0; i < args.size(); i += 4)
processor.S[args[i + 1]].prepare_and(os, args[i],
processor.S[args[i + 2]], processor.S[args[i + 3]],
party, repeat);
party.P->send_relative(os);
party.P->receive_relative(os);
for (size_t i = 0; i < args.size(); i += 4)
processor.S[args[i + 1]].finalize_andrs(os, args[i]);
}
inline void ReplicatedSecret::prepare_and(vector<octetStream>& os, int n,
const ReplicatedSecret& x, const ReplicatedSecret& y,
Thread<ReplicatedSecret>& party, bool repeat)
template<>
inline void ReplicatedSecret<SemiHonestRepSecret>::prepare_and(vector<octetStream>& os, int n,
const ReplicatedSecret<SemiHonestRepSecret>& x, const ReplicatedSecret<SemiHonestRepSecret>& y,
Thread<SemiHonestRepSecret>& party, bool repeat)
{
ReplicatedSecret y_ext;
if (repeat)
@@ -169,19 +174,19 @@ inline void ReplicatedSecret::prepare_and(vector<octetStream>& os, int n,
BitVec(mask & (*this)[0]).pack(os[0], n);
}
void ReplicatedSecret::and_(int n, const ReplicatedSecret& x,
const ReplicatedSecret& y, bool repeat)
template<>
inline void ReplicatedSecret<SemiHonestRepSecret>::finalize_andrs(
vector<octetStream>& os, int n)
{
if (repeat)
andrs(n, x, y);
else
throw runtime_error("call static ReplicatedSecret::ands()");
(*this)[1].unpack(os[1], n);
}
void ReplicatedSecret::andrs(int n, const ReplicatedSecret& x,
const ReplicatedSecret& y)
template<>
void ReplicatedSecret<SemiHonestRepSecret>::andrs(int n,
const ReplicatedSecret<SemiHonestRepSecret>& x,
const ReplicatedSecret<SemiHonestRepSecret>& y)
{
auto& party = ReplicatedParty::s();
auto& party = Thread<SemiHonestRepSecret>::s();
assert(party.P->num_players() == 3);
vector<octetStream>& os = party.os;
os.resize(2);
@@ -193,12 +198,57 @@ void ReplicatedSecret::andrs(int n, const ReplicatedSecret& x,
finalize_andrs(os, n);
}
inline void ReplicatedSecret::finalize_andrs(vector<octetStream>& os, int n)
template<>
void ReplicatedSecret<SemiHonestRepSecret>::and_(int n,
const ReplicatedSecret<SemiHonestRepSecret>& x,
const ReplicatedSecret<SemiHonestRepSecret>& y, bool repeat)
{
(*this)[1].unpack(os[1], n);
if (repeat)
andrs(n, x, y);
else
throw runtime_error("call static ReplicatedSecret::ands()");
}
void ReplicatedSecret::trans(Processor<ReplicatedSecret>& processor,
template<>
void ReplicatedSecret<MaliciousRepSecret>::and_(int n,
const ReplicatedSecret<MaliciousRepSecret>& x,
const ReplicatedSecret<MaliciousRepSecret>& y, bool repeat)
{
(void)n, (void)x, (void)y, (void)repeat;
throw runtime_error("use static method");
}
template<>
void ReplicatedSecret<SemiHonestRepSecret>::and_(Processor<SemiHonestRepSecret>& processor,
const vector<int>& args, bool repeat)
{
auto& party = Thread<SemiHonestRepSecret>::s();
assert(party.P->num_players() == 3);
vector<octetStream>& os = party.os;
os.resize(2);
for (auto& o : os)
o.reset_write_head();
processor.check_args(args, 4);
for (size_t i = 0; i < args.size(); i += 4)
processor.S[args[i + 1]].prepare_and(os, args[i],
processor.S[args[i + 2]], processor.S[args[i + 3]],
party, repeat);
party.P->send_relative(os);
party.P->receive_relative(os);
for (size_t i = 0; i < args.size(); i += 4)
processor.S[args[i + 1]].finalize_andrs(os, args[i]);
}
template<>
void ReplicatedSecret<MaliciousRepSecret>::and_(
Processor<MaliciousRepSecret>& processor, const vector<int>& args,
bool repeat)
{
MaliciousRepThread::s().and_(processor, args, repeat);
}
template<class U>
void ReplicatedSecret<U>::trans(Processor<U>& processor,
int n_outputs, const vector<int>& args)
{
assert(length == 2);
@@ -213,19 +263,21 @@ void ReplicatedSecret::trans(Processor<ReplicatedSecret>& processor,
}
}
void ReplicatedSecret::reveal(Clear& x)
template<class U>
void ReplicatedSecret<U>::reveal(Clear& x)
{
ReplicatedSecret share = *this;
vector<BitVec> opened;
auto& party = ReplicatedParty::s();
party.MC.POpen_Begin(opened, {share}, *party.P);
party.MC.POpen_End(opened, {share}, *party.P);
auto& party = ReplicatedParty<U>::s();
party.MC->POpen_Begin(opened, {share}, *party.P);
party.MC->POpen_End(opened, {share}, *party.P);
x = IntBase(opened[0]);
}
void ReplicatedSecret::random_bit()
template<>
void ReplicatedSecret<SemiHonestRepSecret>::random_bit()
{
auto& party = ReplicatedParty::s();
auto& party = ReplicatedParty<SemiHonestRepSecret>::s();
*this = party.secure_prng.get_bit();
octetStream o;
(*this)[0].pack(o, 1);
@@ -233,4 +285,15 @@ void ReplicatedSecret::random_bit()
(*this)[1].unpack(o, 1);
}
template<>
void ReplicatedSecret<MaliciousRepSecret>::random_bit()
{
MaliciousRepSecret res;
MaliciousRepThread::s().DataF.get_one(DATA_BIT, res);
*this = res;
}
template class ReplicatedSecret<SemiHonestRepSecret>;
template class ReplicatedSecret<MaliciousRepSecret>;
}

View File

@@ -26,16 +26,14 @@ class Processor;
template <class T>
class Thread;
template<class U>
class ReplicatedSecret : public FixedVec<BitVec, 2>
{
typedef FixedVec<BitVec, 2> super;
public:
typedef ReplicatedSecret DynamicType;
typedef BitVec clear;
typedef ReplicatedMC<ReplicatedSecret> MC;
typedef void Inp;
typedef void PO;
typedef ReplicatedBase Protocol;
@@ -46,27 +44,27 @@ public:
static int default_length;
static SwitchableOutput out;
static void store_clear_in_dynamic(Memory<DynamicType>& mem,
static void store_clear_in_dynamic(Memory<U>& mem,
const vector<ClearWriteAccess>& accesses);
static void load(vector< ReadAccess<ReplicatedSecret> >& accesses, const Memory<ReplicatedSecret>& mem);
static void store(Memory<ReplicatedSecret>& mem, vector< WriteAccess<ReplicatedSecret> >& accesses);
static void load(vector< ReadAccess<U> >& accesses, const Memory<U>& mem);
static void store(Memory<U>& mem, vector< WriteAccess<U> >& accesses);
static void andrs(Processor<ReplicatedSecret>& processor, const vector<int>& args)
static void andrs(Processor<U>& processor, const vector<int>& args)
{ and_(processor, args, true); }
static void ands(Processor<ReplicatedSecret>& processor, const vector<int>& args)
static void ands(Processor<U>& processor, const vector<int>& args)
{ and_(processor, args, false); }
static void and_(Processor<ReplicatedSecret>& processor, const vector<int>& args, bool repeat);
static void inputb(Processor<ReplicatedSecret>& processor, const vector<int>& args);
static void and_(Processor<U>& processor, const vector<int>& args, bool repeat);
static void inputb(Processor<U>& processor, const vector<int>& args);
static void trans(Processor<ReplicatedSecret>& processor, int n_outputs,
static void trans(Processor<U>& processor, int n_outputs,
const vector<int>& args);
static BitVec get_mask(int n) { return n >= 64 ? -1 : ((1L << n) - 1); }
static ReplicatedSecret input(int from, Processor<ReplicatedSecret>& processor, int n_bits);
static U input(int from, Processor<U>& processor, int n_bits);
void prepare_input(vector<octetStream>& os, long input, int n_bits, PRNG& secure_prng);
void finalize_input(Thread<ReplicatedSecret>& party, octetStream& o, int from, int n_bits);
void finalize_input(Thread<U>& party, octetStream& o, int from, int n_bits);
ReplicatedSecret() {}
template <class T>
@@ -74,8 +72,8 @@ public:
void load(int n, const Integer& x);
void bitcom(Memory<ReplicatedSecret>& S, const vector<int>& regs);
void bitdec(Memory<ReplicatedSecret>& S, const vector<int>& regs) const;
void bitcom(Memory<U>& S, const vector<int>& regs);
void bitdec(Memory<U>& S, const vector<int>& regs) const;
void xor_(int n, const ReplicatedSecret& x, const ReplicatedSecret& y)
{ *this = x ^ y; (void)n; }
@@ -83,7 +81,7 @@ public:
void andrs(int n, const ReplicatedSecret& x, const ReplicatedSecret& y);
void prepare_and(vector<octetStream>& os, int n,
const ReplicatedSecret& x, const ReplicatedSecret& y,
Thread<ReplicatedSecret>& party, bool repeat);
Thread<U>& party, bool repeat);
void finalize_andrs(vector<octetStream>& os, int n);
void reveal(Clear& x);
@@ -91,6 +89,21 @@ public:
void random_bit();
};
class SemiHonestRepSecret : public ReplicatedSecret<SemiHonestRepSecret>
{
typedef ReplicatedSecret<SemiHonestRepSecret> super;
public:
typedef SemiHonestRepSecret DynamicType;
typedef ReplicatedMC<SemiHonestRepSecret> MC;
SemiHonestRepSecret() {}
template<class T>
SemiHonestRepSecret(const T& other) : super(other) {}
};
}
#endif /* GC_REPLICATEDSECRET_H_ */

View File

@@ -13,7 +13,6 @@
#include "GC/Clear.h"
#include "GC/Memory.h"
#include "GC/Access.h"
#include "GC/Processor.h"
#include "Math/Share.h"
@@ -64,6 +63,8 @@ public:
{ Share<gf2n>::assign(value, first_player ? 0 : 1, mac_key); }
};
template<class T> class Processor;
template <class T>
class Secret
{
@@ -79,7 +80,7 @@ public:
#endif
// dummy
typedef MAC_Check_Base<Secret<T> > MC;
typedef DummyMC MC;
typedef DummyProtocol Protocol;
static string type_string() { return "evaluation secret"; }

View File

@@ -9,6 +9,7 @@
#include "Networking/Player.h"
#include "Tools/random.h"
#include "Processor.h"
#include "ArgTuples.h"
namespace GC
{
@@ -20,6 +21,8 @@ struct ScheduleItem
ScheduleItem(int tape = 0, int arg = 0) : tape(tape), arg(arg) {}
};
template<class T> class ThreadMaster;
template<class T>
class Thread
{
@@ -28,9 +31,10 @@ class Thread
static void* run_thread(void* thread);
public:
ThreadMaster<T>& master;
Machine<T>& machine;
Processor<T> processor;
typename T::MC MC;
typename T::MC* MC;
typename T::Protocol* protocol;
Names& N;
Player* P;
@@ -44,9 +48,11 @@ public:
static Thread<T>& s();
Thread(int thread_num, Machine<T>& machine, Names& N);
Thread(int thread_num, ThreadMaster<T>& master);
virtual ~Thread();
virtual typename T::MC* new_mc() { return new typename T::MC; }
void run();
virtual void pre_run() {}
virtual void run(Program<T>& program);
@@ -54,6 +60,8 @@ public:
void join_tape();
void finish();
int n_interactive_inputs_from_me(InputArgList& args);
};
template<class T>

View File

@@ -25,8 +25,9 @@ void* Thread<T>::run_thread(void* thread)
}
template<class T>
Thread<T>::Thread(int thread_num, Machine<T>& machine, Names& N) :
machine(machine), processor(machine), protocol(0), N(N), P(0),
Thread<T>::Thread(int thread_num, ThreadMaster<T>& master) :
master(master), machine(master.machine), processor(machine),
protocol(0), N(master.N), P(0),
thread_num(thread_num)
{
pthread_create(&thread, 0, run_thread, this);
@@ -35,6 +36,8 @@ Thread<T>::Thread(int thread_num, Machine<T>& machine, Names& N) :
template<class T>
Thread<T>::~Thread()
{
if (MC)
delete MC;
if (P)
delete P;
if (protocol)
@@ -53,8 +56,8 @@ void Thread<T>::run()
else
P = new PlainPlayer(N, thread_num << 16);
protocol = new typename T::Protocol(*P);
string input_file = "Player-Data/Input-P" + to_string(N.my_num()) + "-" + to_string(thread_num);
processor.open_input_file(input_file);
MC = this->new_mc();
processor.open_input_file(N.my_num(), thread_num);
done.push(0);
pre_run();
@@ -67,7 +70,7 @@ void Thread<T>::run()
}
post_run();
MC.Check(*P);
MC->Check(*P);
}
template<class T>
@@ -91,4 +94,16 @@ void Thread<T>::finish()
pthread_join(thread, 0);
}
template<class T>
int GC::Thread<T>::n_interactive_inputs_from_me(InputArgList& args)
{
int res = 0;
if (thread_num == 0 and master.opts.interactive)
res = args.n_inputs_from(P->my_num());
if (res > 0)
cout << "Please enter " << res << " numbers:" << endl;
return res;
}
} /* namespace GC */

View File

@@ -9,6 +9,8 @@
#include "Thread.h"
#include "Program.h"
#include "Processor/OnlineOptions.h"
namespace GC
{
@@ -45,9 +47,11 @@ public:
Machine<T> machine;
Memory<typename T::DynamicType> memory;
OnlineOptions& opts;
static ThreadMaster<T>& s();
ThreadMaster();
ThreadMaster(OnlineOptions& opts);
virtual ~ThreadMaster() {}
void run_tape(int thread_number, int tape_number, int arg);
@@ -56,6 +60,8 @@ public:
virtual Thread<T>* new_thread(int i);
void run();
virtual void post_run() {}
};
} /* namespace GC */

View File

@@ -9,6 +9,8 @@
#include "ReplicatedSecret.h"
#include "Secret.h"
#include "instructions.h"
namespace GC
{
@@ -25,7 +27,8 @@ ThreadMaster<T>& ThreadMaster<T>::s()
}
template<class T>
ThreadMaster<T>::ThreadMaster() : P(0), machine(memory)
ThreadMaster<T>::ThreadMaster(OnlineOptions& opts) :
P(0), machine(memory), opts(opts)
{
if (singleton)
throw runtime_error("there can only be one");
@@ -47,13 +50,13 @@ void ThreadMaster<T>::join_tape(int thread_number)
template<class T>
Thread<T>* ThreadMaster<T>::new_thread(int i)
{
return new Thread<T>(i, machine, N);
return new Thread<T>(i, *this);
}
template<class T>
void ThreadMaster<T>::run()
{
P = new PlainPlayer(N, 1 << 24);
P = new PlainPlayer(N, 0xff << 24);
machine.load_schedule(progname);
for (int i = 0; i < machine.nthreads; i++)
@@ -73,11 +76,30 @@ void ThreadMaster<T>::run()
vector<octetStream> os(P->num_players());
P->Broadcast_Receive(os);
post_run();
NamedCommStats stats = P->comm_stats;
ExecutionStats exe_stats;
for (auto thread : threads)
{
stats += thread->P->comm_stats;
exe_stats += thread->processor.stats;
delete thread;
}
delete P;
for (auto it : exe_stats)
switch (it.first)
{
#define X(NAME, CODE) case NAME: cerr << it.second << " " #NAME << endl; break;
INSTRUCTIONS
}
for (auto it = stats.begin(); it != stats.end(); it++)
if (it->second.data > 0)
cerr << it->first << " " << 1e-6 * it->second.data << " MB" << endl;
cerr << "Time = " << timer.elapsed() << endl;
}

View File

@@ -8,4 +8,8 @@
//#define CHECK_SIZE
//#define COUNT_INSTRUCTIONS
//#define CHECK_SIZE
#endif /* GC_CONFIG_H_ */

View File

@@ -6,19 +6,19 @@
#ifndef GC_INSTRUCTIONS_H_
#define GC_INSTRUCTIONS_H_
#include <valgrind/callgrind.h>
#include "Tools/callgrind.h"
#define P processor
#define PROC processor
#define INST instruction
#define M processor.machine
#define MACH processor.machine
#define R0 instruction.get_r(0)
#define R1 instruction.get_r(1)
#define R2 instruction.get_r(2)
#define S0 processor.S[instruction.get_r(0)]
#define S1 processor.S[instruction.get_r(1)]
#define S2 processor.S[instruction.get_r(2)]
#define PS1 processor.S[instruction.get_r(1)]
#define PS2 processor.S[instruction.get_r(2)]
#define C0 processor.C[instruction.get_r(0)]
#define C1 processor.C[instruction.get_r(1)]
@@ -28,88 +28,89 @@
#define I1 processor.I[instruction.get_r(1)]
#define I2 processor.I[instruction.get_r(2)]
#define N instruction.get_n()
#define IMM instruction.get_n()
#define EXTRA instruction.get_start()
#define MSD M.MS[N]
#define MMC M.MC[N]
#define MID M.MI[N]
#define MSD MACH.MS[IMM]
#define MMC MACH.MC[IMM]
#define MID MACH.MI[IMM]
#define MSI M.MS[I1.get()]
#define MII M.MI[I1.get()]
#define MD M.MD
#define MSI MACH.MS[I1.get()]
#define MII MACH.MI[I1.get()]
#define INSTRUCTIONS \
X(XORS, P.xors(EXTRA)) \
X(XORS, PROC.xors(EXTRA)) \
X(XORC, C0.xor_(C1, C2)) \
X(XORCI, C0.xor_(C1, N)) \
X(ANDRS, T::andrs(P, EXTRA)) \
X(ANDS, T::ands(P, EXTRA)) \
X(INPUTB, T::inputb(P, EXTRA)) \
X(XORCI, C0.xor_(C1, IMM)) \
X(ANDRS, T::andrs(PROC, EXTRA)) \
X(ANDS, T::ands(PROC, EXTRA)) \
X(INPUTB, T::inputb(PROC, EXTRA)) \
X(ADDC, C0 = C1 + C2) \
X(ADDCI, C0 = C1 + N) \
X(MULCI, C0 = C1 * N) \
X(BITDECS, P.bitdecs(EXTRA, S0)) \
X(BITCOMS, P.bitcoms(S0, EXTRA)) \
X(BITDECC, P.bitdecc(EXTRA, C0)) \
X(BITDECINT, P.bitdecint(EXTRA, I0)) \
X(SHRCI, C0 = C1 >> N) \
X(LDBITS, S0.load(R1, N)) \
X(ADDCI, C0 = C1 + IMM) \
X(MULCI, C0 = C1 * IMM) \
X(BITDECS, PROC.bitdecs(EXTRA, S0)) \
X(BITCOMS, PROC.bitcoms(S0, EXTRA)) \
X(BITDECC, PROC.bitdecc(EXTRA, C0)) \
X(BITDECINT, PROC.bitdecint(EXTRA, I0)) \
X(SHRCI, C0 = C1 >> IMM) \
X(SHLCI, C0 = C1 << IMM) \
X(LDBITS, S0.load(R1, IMM)) \
X(LDMS, S0 = MSD) \
X(STMS, MSD = S0) \
X(LDMSI, S0 = MSI) \
X(STMSI, MSI = S0) \
X(LDMC, C0 = MMC) \
X(STMC, MMC = C0) \
X(LDMSD, P.load_dynamic_direct(EXTRA)) \
X(STMSD, P.store_dynamic_direct(EXTRA)) \
X(LDMSDI, P.load_dynamic_indirect(EXTRA)) \
X(STMSDI, P.store_dynamic_indirect(EXTRA)) \
X(STMSDCI, P.store_clear_in_dynamic(EXTRA)) \
X(CONVSINT, S0.load(N, I1)) \
X(LDMSD, PROC.load_dynamic_direct(EXTRA)) \
X(STMSD, PROC.store_dynamic_direct(EXTRA)) \
X(LDMSDI, PROC.load_dynamic_indirect(EXTRA)) \
X(STMSDI, PROC.store_dynamic_indirect(EXTRA)) \
X(STMSDCI, PROC.store_clear_in_dynamic(EXTRA)) \
X(CONVSINT, S0.load(IMM, I1)) \
X(CONVCINT, C0 = I1) \
X(MOVS, S0 = S1) \
X(TRANS, T::trans(P, N, EXTRA)) \
X(BIT, P.random_bit(S0)) \
X(REVEAL, S1.reveal(C0)) \
X(PRINTREG, P.print_reg(R0, N)) \
X(PRINTREGPLAIN, P.print_reg_plain(C0)) \
X(PRINTREGSIGNED, P.print_reg_signed(N, C0)) \
X(PRINTCHR, P.print_chr(N)) \
X(PRINTSTR, P.print_str(N)) \
X(LDINT, I0 = int(N)) \
X(MOVS, S0 = PS1) \
X(TRANS, T::trans(PROC, IMM, EXTRA)) \
X(BIT, PROC.random_bit(S0)) \
X(REVEAL, PS1.reveal(C0)) \
X(PRINTREG, PROC.print_reg(R0, IMM)) \
X(PRINTREGPLAIN, PROC.print_reg_plain(C0)) \
X(PRINTREGSIGNED, PROC.print_reg_signed(IMM, C0)) \
X(PRINTCHR, PROC.print_chr(IMM)) \
X(PRINTSTR, PROC.print_str(IMM)) \
X(PRINTFLOATPLAIN, PROC.print_float(EXTRA)) \
X(CONDPRINTSTR, if(C0.get()) PROC.print_str(IMM)) \
X(LDINT, I0 = int(IMM)) \
X(ADDINT, I0 = I1 + I2) \
X(SUBINT, I0 = I1 - I2) \
X(MULINT, I0 = I1 * I2) \
X(DIVINT, I0 = I1 / I2) \
X(JMP, P.PC += N) \
X(JMPNZ, if (I0 != 0) P.PC += N) \
X(JMPEQZ, if (I0 == 0) P.PC += N) \
X(JMP, PROC.PC += IMM) \
X(JMPNZ, if (I0 != 0) PROC.PC += IMM) \
X(JMPEQZ, if (I0 == 0) PROC.PC += IMM) \
X(EQZC, I0 = I1 == 0) \
X(LTZC, I0 = I1 < 0) \
X(LTC, I0 = I1 < I2) \
X(GTC, I0 = I1 > I2) \
X(EQC, I0 = I1 == I2) \
X(JMPI, P.PC += I0) \
X(JMPI, PROC.PC += I0) \
X(LDMINT, I0 = MID) \
X(STMINT, MID = I0) \
X(LDMINTI, I0 = MII) \
X(STMINTI, MII = I0) \
X(PUSHINT, P.pushi(I0.get())) \
X(POPINT, long x; P.popi(x); I0 = x) \
X(PUSHINT, PROC.pushi(I0.get())) \
X(POPINT, long x; PROC.popi(x); I0 = x) \
X(MOVINT, I0 = I1) \
X(LDARG, I0 = P.get_arg()) \
X(STARG, P.set_arg(I0.get())) \
X(TIME, M.time()) \
X(START, M.start(N)) \
X(STOP, M.stop(N)) \
X(LDARG, I0 = PROC.get_arg()) \
X(STARG, PROC.set_arg(I0.get())) \
X(TIME, MACH.time()) \
X(START, MACH.start(IMM)) \
X(STOP, MACH.stop(IMM)) \
X(GLDMS, ) \
X(GLDMC, ) \
X(PRINTINT, S0.out << I0) \
X(STARTGRIND, CALLGRIND_START_INSTRUMENTATION) \
X(STOPGRIND, CALLGRIND_STOP_INSTRUMENTATION) \
X(RUN_TAPE, M.run_tape(R0, N, R1)) \
X(JOIN_TAPE, M.join_tape(R0)) \
X(RUN_TAPE, MACH.run_tape(R0, IMM, R1)) \
X(JOIN_TAPE, MACH.join_tape(R0)) \
#endif /* GC_INSTRUCTIONS_H_ */

View File

@@ -28,7 +28,7 @@ endif
COMMON = $(MATH) $(TOOLS) $(NETWORK) $(AUTH)
COMPLETE = $(COMMON) $(PROCESSOR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(GC) $(OT)
YAO = $(patsubst %.cpp,%.o,$(wildcard Yao/*.cpp)) $(OT) $(GC)
BMR = $(patsubst %.cpp,%.o,$(wildcard BMR/*.cpp BMR/network/*.cpp)) $(COMMON) $(PROCESSOR) $(GC)
BMR = $(patsubst %.cpp,%.o,$(wildcard BMR/*.cpp BMR/network/*.cpp)) $(COMMON) $(PROCESSOR)
LIB = libSPDZ.a
@@ -39,7 +39,7 @@ OBJS = $(BMR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(YAO) $(COMPLETE)
DEPS := $(OBJS:.o=.d)
all: gen_input online offline externalIO yao replicated-bin-party.x replicated-ring-party.x
all: gen_input online offline externalIO yao replicated
ifeq ($(USE_GF2N_LONG),1)
all: bmr
@@ -70,10 +70,20 @@ she-offline: Check-Offline.x spdz2-offline.x
overdrive: simple-offline.x pairwise-offline.x cnc-offline.x
Fake-Offline.x: Fake-Offline.cpp $(COMMON) $(PROCESSOR)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
rep-field: malicious-rep-bin-party.x replicated-field-party.x Setup.x
Check-Offline.x: Check-Offline.cpp $(COMMON) $(PROCESSOR)
rep-ring: replicated-ring-party.x Fake-Offline.x
rep-bin: replicated-bin-party.x malicious-rep-bin-party.x Fake-Offline.x
replicated: rep-field rep-ring rep-bin
tldr: malicious-rep-field-party.x Setup.x
Fake-Offline.x: Fake-Offline.cpp $(COMMON) $(PROCESSOR)
$(CXX) $(CFLAGS) -o $@ Fake-Offline.cpp $(COMMON) $(PROCESSOR) $(LDLIBS)
Check-Offline.x: Check-Offline.cpp $(COMMON) $(PROCESSOR) Auth/fake-stuff.hpp
$(CXX) $(CFLAGS) Check-Offline.cpp -o Check-Offline.x $(COMMON) $(PROCESSOR) $(LDLIBS)
Server.x: Server.cpp $(COMMON)
@@ -82,6 +92,9 @@ Server.x: Server.cpp $(COMMON)
Player-Online.x: Player-Online.cpp $(COMMON) $(PROCESSOR)
$(CXX) $(CFLAGS) Player-Online.cpp -o Player-Online.x $(COMMON) $(PROCESSOR) $(LDLIBS)
Setup.x: Setup.cpp $(COMMON)
$(CXX) $(CFLAGS) Setup.cpp -o Setup.x $(COMMON) $(LDLIBS)
ifeq ($(USE_GF2N_LONG),1)
ot.x: $(OT) $(COMMON) OT/OText_main.cpp $(LIBSIMPLEOT)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
@@ -106,7 +119,7 @@ gen_input_fp.x: Scripts/gen_input_fp.cpp $(COMMON)
$(CXX) $(CFLAGS) Scripts/gen_input_fp.cpp -o gen_input_fp.x $(COMMON) $(LDLIBS)
gc-emulate.x: $(GC) $(COMMON) $(PROCESSOR) gc-emulate.cpp $(GC)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) $(BOOST)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
ifeq ($(USE_GF2N_LONG),1)
bmr-program-party.x: $(BMR) bmr-program-party.cpp
@@ -152,11 +165,20 @@ galois-degree.x: $(COMMON) galois-degree.cpp
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
replicated-bin-party.x: $(COMMON) $(GC) replicated-bin-party.cpp
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) $(BOOST)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
malicious-rep-bin-party.x: $(COMMON) $(GC) malicious-rep-bin-party.cpp
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
replicated-ring-party.x: replicated-ring-party.cpp $(PROCESSOR) $(COMMON)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
replicated-field-party.x: replicated-field-party.cpp $(PROCESSOR) $(COMMON)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
malicious-rep-field-party.x: malicious-rep-field-party.cpp $(PROCESSOR) $(COMMON)
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
$(LIBSIMPLEOT): SimpleOT/Makefile
$(MAKE) -C SimpleOT
@@ -166,5 +188,18 @@ OT/BaseOT.o: SimpleOT/Makefile
SimpleOT/Makefile:
git submodule update --init SimpleOT
.PHONY: mpir
mpir:
git submodule update --init mpir
cd mpir; \
libtoolize --force; \
aclocal; \
autoheader; \
automake --force-missing --add-missing; \
autoconf; \
./configure --enable-cxx;
$(MAKE) -C mpir
sudo $(MAKE) -C mpir install
clean:
-rm */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o

View File

@@ -7,12 +7,16 @@
#define MATH_BITVEC_H_
#include "Integer.h"
#include "field_types.h"
class BitVec : public IntBase
{
public:
static const int n_bits = sizeof(a) * 8;
static char type_char() { return 'B'; }
static DataFieldType field_type() { return DATA_GF2; }
BitVec() {}
BitVec(long a) : IntBase(a) {}
BitVec(const IntBase& a) : IntBase(a) {}
@@ -24,6 +28,9 @@ public:
BitVec& operator+=(const BitVec& other) { *this ^= other; return *this; }
BitVec extend_bit() const { return -(a & 1); }
BitVec mask(int n) const { return n < n_bits ? *this & ((1L << n) - 1) : *this; }
void mul(const BitVec& a, const BitVec& b) { *this = a * b; }
void pack(octetStream& os, int n = n_bits) const { os.store_int(a, DIV_CEIL(n, 8)); }
void unpack(octetStream& os, int n = n_bits) { a = os.get_int(DIV_CEIL(n, 8)); }

View File

@@ -35,13 +35,13 @@ public:
{
return T::type_string() + "^" + to_string(L);
}
static char type_char()
static string type_short()
{
return T::type_char();
return string(1, T::type_char());
}
static DataFieldType field_type()
{
return DATA_MODP;
return T::field_type();
}
FixedVec<T, L>(const T& other = 0)
@@ -71,8 +71,8 @@ public:
}
void assign(const char* buffer)
{
for (auto& x : v)
x.assign(buffer);
for (int i = 0; i < L; i++)
v[i].assign(buffer + i * T::size());
}
void assign_zero()
@@ -144,6 +144,21 @@ public:
return res;
}
FixedVec<T, L>operator*(const FixedVec<T, L>& other) const
{
FixedVec<T, L> res;
res.mul(*this, other);
return res;
}
FixedVec<T, L>operator/(const FixedVec<T, L>& other) const
{
FixedVec<T, L> res;
for (int i = 0; i < L; i++)
res[i] = v[i] / other[i];
return res;
}
FixedVec<T, L>operator^(const FixedVec<T, L>& other) const
{
FixedVec<T, L> res;
@@ -166,6 +181,12 @@ public:
return *this;
}
FixedVec<T, L>& operator/=(const FixedVec<T, L>& other)
{
*this = *this / other;
return *this;
}
FixedVec<T, L>& operator^=(const FixedVec<T, L>& other)
{
for (int i = 0; i < L; i++)
@@ -196,6 +217,12 @@ public:
return res;
}
FixedVec<T, L>& operator>>=(int i)
{
*this = *this >> i;
return *this;
}
T sum() const
{
T res = 0;
@@ -212,6 +239,14 @@ public:
return res;
}
FixedVec<T, L> mask(int n_bits) const
{
FixedVec<T, L> res;
for (int i = 0; i < L; i++)
res[i] = v[i].mask(n_bits);
return res;
}
void randomize(PRNG& G)
{
for (auto& x : v)
@@ -251,6 +286,12 @@ public:
}
};
template <class T, int L>
FixedVec<T, L> operator*(const T& a, const FixedVec<T, L>& b)
{
return b * a;
}
template <class T, int L>
ostream& operator<<(ostream& os, const FixedVec<T, L>& v)
{

View File

@@ -31,3 +31,18 @@ void to_signed_bigint(bigint& res, const Integer& x, int n)
if (x < 0)
res.negate();
}
void Integer::reqbl(int n)
{
if ((int)n < 0 && size() * 8 != -(int)n)
{
throw Processor_Error(
"Program compiled for rings of length " + to_string(-(int)n)
+ " but VM supports only "
+ to_string(size() * 8));
}
else if ((int)n > 0)
{
throw Processor_Error("Program compiled for fields not rings");
}
}

View File

@@ -12,6 +12,7 @@ using namespace std;
#include "Tools/octetStream.h"
#include "Tools/random.h"
#include "bigint.h"
#include "field_types.h"
// Functionality shared between integers and bit vectors
@@ -30,9 +31,16 @@ public:
long get() const { return a; }
bool get_bit(int i) const { return (a >> i) & 1; }
unsigned long debug() const { return a; }
void assign(long x) { *this = x; }
void assign(const char* buffer) { avx_memcpy(&a, buffer, sizeof(a)); }
void assign_zero() { a = 0; }
void assign_one() { a = 1; }
bool is_zero() const { return a == 0; }
bool is_one() const { return a == 1; }
bool is_bit() const { return is_zero() or is_one(); }
long operator>>(const IntBase& other) const { return a >> other.a; }
long operator<<(const IntBase& other) const { return a << other.a; }
@@ -44,6 +52,8 @@ public:
bool operator==(const IntBase& other) const { return a == other.a; }
bool operator!=(const IntBase& other) const { return a != other.a; }
bool equal(const IntBase& other) const { return *this == other; }
long operator^=(const IntBase& other) { return a ^= other.a; }
long operator&=(const IntBase& other) { return a &= other.a; }
@@ -67,6 +77,9 @@ class Integer : public IntBase
typedef Integer clear;
static char type_char() { return 'R'; }
static DataFieldType field_type() { return DATA_INT64; }
static void reqbl(int n);
Integer() { a = 0; }
Integer(long a) : IntBase(a) {}
@@ -74,12 +87,6 @@ class Integer : public IntBase
void convert_destroy(bigint& other) { *this = other.get_si(); }
void assign_one() { a = 1; }
bool is_zero() const { return a == 0; }
bool is_one() const { return a == 1; }
bool is_bit() const { return is_zero() or is_one(); }
long operator+(const Integer& other) const { return a + other.a; }
long operator-(const Integer& other) const { return a - other.a; }
long operator*(const Integer& other) const { return a * other.a; }
@@ -126,6 +133,11 @@ inline void to_bigint(bigint& res, const Integer& x)
res = (unsigned long)x.get();
}
inline void to_signed_bigint(bigint& res, const Integer& x)
{
res = x.get();
}
void to_signed_bigint(bigint& res, const Integer& x, int n);
// slight misnomer

41
Math/MaliciousRep3Share.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* MaliciousRep3Share.h
*
*/
#ifndef MATH_MALICIOUSREP3SHARE_H_
#define MATH_MALICIOUSREP3SHARE_H_
#include "Rep3Share.h"
#include "gfp.h"
template<class T> class HashMaliciousRepMC;
template<class T> class Beaver;
template<class T>
class MaliciousRep3Share : public Rep3Share<T>
{
typedef Rep3Share<T> super;
public:
typedef Beaver<MaliciousRep3Share<T>> Protocol;
typedef HashMaliciousRepMC<MaliciousRep3Share<T>> MAC_Check;
typedef MAC_Check Direct_MC;
typedef ReplicatedInput<MaliciousRep3Share<T>> Input;
typedef ReplicatedPrivateOutput<MaliciousRep3Share<T>> PrivateOutput;
static string type_short()
{
return "M" + string(1, gfp::type_char());
}
MaliciousRep3Share()
{
}
template<class U>
MaliciousRep3Share(const U& other) : super(other)
{
}
};
#endif /* MATH_MALICIOUSREP3SHARE_H_ */

View File

@@ -10,10 +10,11 @@
#include "Math/Integer.h"
#include "Processor/Replicated.h"
class Rep3Share: public FixedVec<Integer, 2>
template<class T>
class Rep3Share : public FixedVec<T, 2>
{
public:
typedef Integer clear;
typedef T clear;
typedef Replicated<Rep3Share> Protocol;
typedef ReplicatedMC<Rep3Share> MAC_Check;
@@ -21,33 +22,37 @@ public:
typedef ReplicatedInput<Rep3Share> Input;
typedef ReplicatedPrivateOutput<Rep3Share> PrivateOutput;
static char type_char()
static string type_short()
{
return clear::type_char();
return "R" + string(1, clear::type_char());
}
static string type_string()
{
return "replicated " + T::type_string();
}
Rep3Share()
{
}
Rep3Share(const FixedVec<Integer, 2>& other)
Rep3Share(const FixedVec<T, 2>& other)
{
FixedVec<Integer, 2>::operator=(other);
FixedVec<T, 2>::operator=(other);
}
Rep3Share(Integer value, int my_num)
Rep3Share(T value, int my_num)
{
Replicated<Rep3Share>::assign(*this, value, my_num);
}
// Share<T> compatibility
void assign(clear other, int my_num, const Integer& alphai)
void assign(clear other, int my_num, const T& alphai)
{
(void)alphai;
*this = Rep3Share(other, my_num);
}
void assign(const char* buffer)
{
FixedVec<Integer, 2>::assign(buffer);
FixedVec<T, 2>::assign(buffer);
}
void add(const Rep3Share& x, const Rep3Share& y)
@@ -60,33 +65,39 @@ public:
}
void add(const Rep3Share& S, const clear aa, int my_num,
const Integer& alphai)
const T& alphai)
{
(void)alphai;
*this = S + Rep3Share(aa, my_num);
}
void sub(const Rep3Share& S, const clear& aa, int my_num,
const Integer& alphai)
const T& alphai)
{
(void)alphai;
*this = S - Rep3Share(aa, my_num);
}
void sub(const clear& aa, const Rep3Share& S, int my_num,
const Integer& alphai)
const T& alphai)
{
(void)alphai;
*this = Rep3Share(aa, my_num) - S;
}
void mul_by_bit(const Rep3Share& x, const T& y)
{
(void) x, (void) y;
throw not_implemented();
}
void pack(octetStream& os, bool full = true) const
{
(void)full;
FixedVec<Integer, 2>::pack(os);
FixedVec<T, 2>::pack(os);
}
void unpack(octetStream& os, bool full = true)
{
(void)full;
FixedVec<Integer, 2>::unpack(os);
FixedVec<T, 2>::unpack(os);
}
};

View File

@@ -45,8 +45,8 @@ class Share
static string type_string()
{ return T::type_string(); }
static char type_char()
{ return T::type_char(); }
static string type_short()
{ return string(1, T::type_char()); }
static DataFieldType field_type()
{ return T::field_type(); }

View File

@@ -6,6 +6,7 @@
void Zp_Data::init(const bigint& p,bool mont)
{ pr=p;
mask=(1<<((mpz_sizeinbase(pr.get_mpz_t(),2)-1)%(8*sizeof(mp_limb_t))))-1;
pr_byte_length = numBytes(pr);
montgomery=mont;
t=mpz_size(pr.get_mpz_t());

View File

@@ -45,6 +45,7 @@ class Zp_Data
bigint pr;
mp_limb_t mask;
size_t pr_byte_length;
void assign(const Zp_Data& Zp);
void init(const bigint& p,bool mont=true);
@@ -55,7 +56,7 @@ class Zp_Data
void unpack(octetStream& o);
// This one does nothing, needed so as to make vectors of Zp_Data
Zp_Data() : montgomery(0), pi(0), mask(0) { t=MAX_MOD_SZ; }
Zp_Data() : montgomery(0), pi(0), mask(0), pr_byte_length(0) { t=MAX_MOD_SZ; }
// The main init funciton
Zp_Data(const bigint& p,bool mont=true)

View File

@@ -1,9 +1,22 @@
#include "bigint.h"
#include "gfp.h"
#include "Integer.h"
#include "GC/Clear.h"
#include "Exceptions/Exceptions.h"
class gmp_random
{
public:
gmp_randclass Gen;
gmp_random() : Gen(gmp_randinit_default)
{
Gen.seed(0);
}
};
thread_local bigint bigint::tmp;
thread_local gmp_random bigint::random;
bigint sqrRootMod(const bigint& a,const bigint& p)
{
@@ -18,13 +31,11 @@ bigint sqrRootMod(const bigint& a,const bigint& p)
}
else
{ // Shanks algorithm
gmp_randclass Gen(gmp_randinit_default);
Gen.seed(0);
bigint x,y,n,q,t,b,temp;
// Find n such that (n/p)=-1
int leg=1;
while (leg!=-1)
{ n=Gen.get_z_range(p);
{ n=bigint::random.Gen.get_z_range(p);
leg=mpz_legendre(n.get_mpz_t(),p.get_mpz_t());
}
// Split p-1 = 2^e q
@@ -134,6 +145,27 @@ int limb_size<int>()
return 0;
}
template<class T>
mpf_class bigint::get_float(T v, Integer exp, T z, T s)
{
bigint tmp;
to_signed_bigint(tmp, v);
mpf_class res = tmp;
if (exp > 0)
mpf_mul_2exp(res.get_mpf_t(), res.get_mpf_t(), exp.get());
else
mpf_div_2exp(res.get_mpf_t(), res.get_mpf_t(), -exp.get());
if (z.is_one())
res = 0;
if (s.is_one())
{
res *= -1;
}
if (not z.is_bit() or not s.is_bit())
throw Processor_Error("invalid floating point number");
return res;
}
#ifdef REALLOC_POLICE
void bigint::lottery()
{
@@ -142,3 +174,7 @@ void bigint::lottery()
throw runtime_error("much deallocation");
}
#endif
template mpf_class bigint::get_float(gfp, Integer, gfp, gfp);
template mpf_class bigint::get_float(Integer, Integer, Integer, Integer);
template mpf_class bigint::get_float(GC::Clear, Integer, GC::Clear, GC::Clear);

View File

@@ -22,11 +22,17 @@ enum ReportType
};
class gfp;
class gmp_random;
class Integer;
class bigint : public mpz_class
{
public:
static thread_local bigint tmp;
static thread_local gmp_random random;
template<class T>
static mpf_class get_float(T v, Integer exp, T z, T s);
bigint() : mpz_class() {}
template <class T>

View File

@@ -7,7 +7,7 @@
#define MATH_FIELD_TYPES_H_
enum DataFieldType { DATA_MODP, DATA_GF2N, N_DATA_FIELD_TYPE };
enum DataFieldType { DATA_MODP, DATA_GF2N, DATA_GF2, DATA_INT64, N_DATA_FIELD_TYPE };
#endif /* MATH_FIELD_TYPES_H_ */

View File

@@ -349,3 +349,49 @@ void gf2n_short::input(istream& s,bool human)
a &= mask;
}
// Expansion is by x=y^5+1 (as we embed GF(256) into GF(2^40)
void expand_byte(gf2n_short& a,int b)
{
gf2n_short x,xp;
x.assign(32+1);
xp.assign_one();
a.assign_zero();
while (b!=0)
{ if ((b&1)==1)
{ a.add(a,xp); }
xp.mul(x);
b>>=1;
}
}
// Have previously worked out the linear equations we need to solve
void collapse_byte(int& b,const gf2n_short& aa)
{
word w=aa.get();
int e35=(w>>35)&1;
int e30=(w>>30)&1;
int e25=(w>>25)&1;
int e20=(w>>20)&1;
int e15=(w>>15)&1;
int e10=(w>>10)&1;
int e5=(w>>5)&1;
int e0=w&1;
int a[8];
a[7]=e35;
a[6]=e30^a[7];
a[5]=e25^a[7];
a[4]=e20^a[5]^a[6]^a[7];
a[3]=e15^a[7];
a[2]=e10^a[3]^a[6]^a[7];
a[1]=e5^a[3]^a[5]^a[7];
a[0]=e0^a[1]^a[2]^a[3]^a[4]^a[5]^a[6]^a[7];
b=0;
for (int i=7; i>=0; i--)
{ b=b<<1;
b+=a[i];
}
}

View File

@@ -12,6 +12,11 @@ using namespace std;
#include "Math/gf2nlong.h"
#include "Math/field_types.h"
class gf2n_short;
void expand_byte(gf2n_short& a,int b);
void collapse_byte(int& b,const gf2n_short& a);
/* This interface compatible with the gfp interface
* which then allows us to template the Share
* data type.
@@ -138,12 +143,13 @@ class gf2n_short
// x * y when one of x,y is a bit
void mul_by_bit(const gf2n_short& x, const gf2n_short& y) { a = x.a * y.a; }
gf2n_short operator+(const gf2n_short& x) { gf2n_short res; res.add(*this, x); return res; }
gf2n_short operator*(const gf2n_short& x) { gf2n_short res; res.mul(*this, x); return res; }
gf2n_short operator+(const gf2n_short& x) const { gf2n_short res; res.add(*this, x); return res; }
gf2n_short operator*(const gf2n_short& x) const { gf2n_short res; res.mul(*this, x); return res; }
gf2n_short& operator+=(const gf2n_short& x) { add(x); return *this; }
gf2n_short& operator*=(const gf2n_short& x) { mul(x); return *this; }
gf2n_short operator-(const gf2n_short& x) { gf2n_short res; res.add(*this, x); return res; }
gf2n_short operator-(const gf2n_short& x) const { gf2n_short res; res.add(*this, x); return res; }
gf2n_short& operator-=(const gf2n_short& x) { sub(x); return *this; }
gf2n_short operator/(const gf2n_short& x) const { gf2n_short tmp; tmp.invert(x); return *this * tmp; }
void square();
void square(const gf2n_short& aa);
@@ -161,12 +167,12 @@ class gf2n_short
void SHL(const gf2n_short& x,int n) { a=(x.a<<n)&mask; }
void SHR(const gf2n_short& x,int n) { a=x.a>>n; }
gf2n_short operator&(const gf2n_short& x) { gf2n_short res; res.AND(*this, x); return res; }
gf2n_short operator^(const gf2n_short& x) { gf2n_short res; res.XOR(*this, x); return res; }
gf2n_short operator|(const gf2n_short& x) { gf2n_short res; res.OR(*this, x); return res; }
gf2n_short operator!() { gf2n_short res; res.NOT(*this); return res; }
gf2n_short operator<<(int i) { gf2n_short res; res.SHL(*this, i); return res; }
gf2n_short operator>>(int i) { gf2n_short res; res.SHR(*this, i); return res; }
gf2n_short operator&(const gf2n_short& x) const { gf2n_short res; res.AND(*this, x); return res; }
gf2n_short operator^(const gf2n_short& x) const { gf2n_short res; res.XOR(*this, x); return res; }
gf2n_short operator|(const gf2n_short& x) const { gf2n_short res; res.OR(*this, x); return res; }
gf2n_short operator!() const { gf2n_short res; res.NOT(*this); return res; }
gf2n_short operator<<(int i) const { gf2n_short res; res.SHL(*this, i); return res; }
gf2n_short operator>>(int i) const { gf2n_short res; res.SHR(*this, i); return res; }
/* Crap RNG */
void randomize(PRNG& G);

View File

@@ -187,12 +187,13 @@ class gf2n_long
// x * y when one of x,y is a bit
void mul_by_bit(const gf2n_long& x, const gf2n_long& y) { a = x.a.a * y.a.a; }
gf2n_long operator+(const gf2n_long& x) { gf2n_long res; res.add(*this, x); return res; }
gf2n_long operator*(const gf2n_long& x) { gf2n_long res; res.mul(*this, x); return res; }
gf2n_long operator+(const gf2n_long& x) const { gf2n_long res; res.add(*this, x); return res; }
gf2n_long operator*(const gf2n_long& x) const { gf2n_long res; res.mul(*this, x); return res; }
gf2n_long& operator+=(const gf2n_long& x) { add(x); return *this; }
gf2n_long& operator*=(const gf2n_long& x) { mul(x); return *this; }
gf2n_long operator-(const gf2n_long& x) { gf2n_long res; res.add(*this, x); return res; }
gf2n_long operator-(const gf2n_long& x) const { gf2n_long res; res.add(*this, x); return res; }
gf2n_long& operator-=(const gf2n_long& x) { sub(x); return *this; }
gf2n_long operator/(const gf2n_long& x) const { gf2n_long tmp; tmp.invert(x); return *this * tmp; }
void square();
void square(const gf2n_long& aa);
@@ -210,12 +211,12 @@ class gf2n_long
void SHL(const gf2n_long& x,int n) { a=(x.a<<n)&mask; }
void SHR(const gf2n_long& x,int n) { a=x.a>>n; }
gf2n_long operator&(const gf2n_long& x) { gf2n_long res; res.AND(*this, x); return res; }
gf2n_long operator^(const gf2n_long& x) { gf2n_long res; res.XOR(*this, x); return res; }
gf2n_long operator|(const gf2n_long& x) { gf2n_long res; res.OR(*this, x); return res; }
gf2n_long operator!() { gf2n_long res; res.NOT(*this); return res; }
gf2n_long operator<<(int i) { gf2n_long res; res.SHL(*this, i); return res; }
gf2n_long operator>>(int i) { gf2n_long res; res.SHR(*this, i); return res; }
gf2n_long operator&(const gf2n_long& x) const { gf2n_long res; res.AND(*this, x); return res; }
gf2n_long operator^(const gf2n_long& x) const { gf2n_long res; res.XOR(*this, x); return res; }
gf2n_long operator|(const gf2n_long& x) const { gf2n_long res; res.OR(*this, x); return res; }
gf2n_long operator!() const { gf2n_long res; res.NOT(*this); return res; }
gf2n_long operator<<(int i) const { gf2n_long res; res.SHL(*this, i); return res; }
gf2n_long operator>>(int i) const { gf2n_long res; res.SHR(*this, i); return res; }
/* Crap RNG */
void randomize(PRNG& G);

View File

@@ -131,3 +131,25 @@ gfp gfp::sqrRoot()
to_gfp(temp, ti);
return temp;
}
void gfp::reqbl(int n)
{
if ((int)n > 0 && gfp::pr() < bigint(1) << (n-1))
{
cout << "Tape requires prime of bit length " << n << endl;
throw invalid_params();
}
else if ((int)n < 0)
{
throw Processor_Error("Program compiled for rings not fields");
}
}
void to_signed_bigint(bigint& ans, const gfp& x)
{
to_bigint(ans, x);
// get sign and abs(x)
bigint& p_half = bigint::tmp = (gfp::pr()-1)/2;
if (mpz_cmp(ans.get_mpz_t(), p_half.get_mpz_t()) > 0)
ans = gfp::pr() - ans;
}

View File

@@ -51,16 +51,26 @@ class gfp
static int size() { return t() * sizeof(mp_limb_t); }
static void reqbl(int n);
void assign(const gfp& g) { a=g.a; }
void assign_zero() { assignZero(a,ZpD); }
void assign_one() { assignOne(a,ZpD); }
void assign(word aa) { bigint::tmp=aa; to_gfp(*this,bigint::tmp); }
void assign(long aa) { bigint::tmp=aa; to_gfp(*this,bigint::tmp); }
void assign(int aa) { bigint::tmp=aa; to_gfp(*this,bigint::tmp); }
void assign(long aa)
{
if (aa == 0)
assignZero(a, ZpD);
else
to_gfp(*this, bigint::tmp = aa);
}
void assign(int aa) { assign(long(aa)); }
void assign(const char* buffer) { a.assign(buffer, ZpD.get_t()); }
modp get() const { return a; }
unsigned long debug() const { return a.get_limb(0); }
// Assumes prD behind x is equal to ZpD
void assign(modp& x) { a=x; }
@@ -134,6 +144,7 @@ class gfp
gfp operator+(const gfp& x) const { gfp res; res.add(*this, x); return res; }
gfp operator-(const gfp& x) const { gfp res; res.sub(*this, x); return res; }
gfp operator*(const gfp& x) const { gfp res; res.mul(*this, x); return res; }
gfp operator/(const gfp& x) const { gfp tmp; tmp.invert(x); return *this * tmp; }
gfp& operator+=(const gfp& x) { add(x); return *this; }
gfp& operator-=(const gfp& x) { sub(x); return *this; }
gfp& operator*=(const gfp& x) { mul(x); return *this; }
@@ -211,5 +222,6 @@ class gfp
{ to_modp(ans.a,x,ans.ZpD); }
};
void to_signed_bigint(bigint& ans,const gfp& x);
#endif

View File

@@ -11,8 +11,7 @@ bool modp::rewind = false;
void modp::randomize(PRNG& G, const Zp_Data& ZpD)
{
bigint x=G.randomBnd(ZpD.pr);
memcpy(this->x, x.get_mpz_t()->_mp_d, ZpD.get_t() * sizeof(mp_limb_t));
G.randomBnd(x, ZpD.get_prA(), ZpD.pr_byte_length);
}
void modp::pack(octetStream& o,const Zp_Data& ZpD) const

View File

@@ -199,7 +199,8 @@ Player::~Player()
cerr << it->first << " " << 1e-6 * it->second.data << " MB in "
<< it->second.rounds << " rounds, taking " << it->second.timer.elapsed()
<< " seconds" << endl;
cerr << "Receiving took " << timer.elapsed() << " seconds" << endl;
if (timer.elapsed() > 0)
cerr << "Receiving took " << timer.elapsed() << " seconds" << endl;
}
@@ -213,7 +214,7 @@ void MultiPlayer<int>::setup_sockets(const vector<string>& names,const vector<in
sockets.resize(nplayers);
// Set up the client side
for (int i=player_no; i<nplayers; i++) {
int pn=id_base+i*nplayers+player_no;
int pn=id_base+player_no;
if (i==player_no) {
const char* localhost = "127.0.0.1";
fprintf(stderr, "Setting up send to self socket to %s:%d with id 0x%x\n",localhost,ports[i],pn);
@@ -227,7 +228,7 @@ void MultiPlayer<int>::setup_sockets(const vector<string>& names,const vector<in
send_to_self_socket = sockets[player_no];
// Setting up the server side
for (int i=0; i<=player_no; i++) {
int id=id_base+player_no*nplayers+i;
int id=id_base+i;
fprintf(stderr, "As a server, waiting for client with id 0x%x to connect.\n",id);
sockets[i] = server.get_connection_socket(id);
}
@@ -340,8 +341,7 @@ template<class T>
void MultiPlayer<T>::pass_around(octetStream& o, int offset) const
{
TimeScope ts(comm_stats["Passing around"].add(o));
o.exchange(sockets.at((my_num() + offset) % num_players()),
sockets.at((my_num() + num_players() - offset) % num_players()));
o.exchange(sockets.at(get_player(offset)), sockets.at(get_player(-offset)));
sent += o.get_length();
}
@@ -563,6 +563,7 @@ static pair<keyinfo,keyinfo> sts_responder(int socket, CommsecKeysPackage *keys,
void TwoPartyPlayer::setup_sockets(int other_player, const Names &nms, int portNum, int id)
{
id += 0xF << 28;
const char *hostname = nms.names[other_player].c_str();
ServerSocket *server = nms.server;
if (is_server) {
@@ -637,5 +638,18 @@ void TwoPartyPlayer::exchange(octetStream& o) const
o.exchange(socket, socket);
}
CommStats& CommStats::operator +=(const CommStats& other)
{
data += other.data;
return *this;
}
NamedCommStats& NamedCommStats::operator +=(const NamedCommStats& other)
{
for (auto it = other.begin(); it != other.end(); it++)
(*this)[it->first] += it->second;
return *this;
}
template class MultiPlayer<int>;
template class MultiPlayer<ssl_socket*>;

View File

@@ -125,6 +125,13 @@ struct CommStats
Timer timer;
CommStats() : data(0), rounds(0) {}
Timer& add(const octetStream& os) { data += os.get_length(); rounds++; return timer; }
CommStats& operator+=(const CommStats& other);
};
class NamedCommStats : public map<string, CommStats>
{
public:
NamedCommStats& operator+=(const NamedCommStats& other);
};
class Player : public PlayerBase
@@ -134,9 +141,9 @@ protected:
mutable blk_SHA_CTX ctx;
mutable map<string,CommStats> comm_stats;
public:
mutable NamedCommStats comm_stats;
Player(const Names& Nms);
virtual ~Player();
@@ -144,6 +151,7 @@ public:
int my_num() const { return player_no; }
int get_offset(int other_player) const { return positive_modulo(other_player - my_num(), num_players()); }
int get_player(int offset) const { return positive_modulo(offset + my_num(), num_players()); }
virtual bool is_encrypted() { return false; }

View File

@@ -6,6 +6,12 @@
#include "Exceptions/Exceptions.h"
#include "Tools/avx_memcpy.h"
#ifdef __APPLE__
# include <libkern/OSByteOrder.h>
#define htole64(x) OSSwapHostToLittleInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#endif
typedef unsigned char octet;

View File

@@ -1,9 +1,12 @@
#include "Processor/Machine.h"
#include "Processor/OnlineOptions.h"
#include "Math/Setup.h"
#include "Tools/ezOptionParser.h"
#include "Tools/Config.h"
#include "Networking/Server.h"
#include "Processor/Online-Thread.hpp"
#include <iostream>
#include <map>
#include <string>
@@ -13,6 +16,7 @@ using namespace std;
int main(int argc, const char** argv)
{
ez::ezOptionParser opt;
OnlineOptions online_opts(opt, argc, argv);
opt.syntax = "./Player-Online.x [OPTIONS] <playernum> <progname>\n";
opt.example = "./Player-Online.x -lgp 64 -lg2 128 -m new 0 sample-prog\n./Player-Online.x -pn 13000 -h localhost 1 sample-prog\n";
@@ -27,11 +31,11 @@ int main(int argc, const char** argv)
"--lgp" // Flag token.
);
opt.add(
"40", // Default.
to_string(gf2n::default_degree()).c_str(), // Default.
0, // Required?
1, // Number of args expected.
0, // Delimiter if expecting multiple args.
"Bit length of GF(2^n) field (default: 40)", // Help description.
("Bit length of GF(2^n) field (default: " + to_string(gf2n::default_degree()) + ")").c_str(), // Help description.
"-lg2", // Flag token.
"--lg2" // Flag token.
);
@@ -149,6 +153,7 @@ int main(int argc, const char** argv)
"--nparties" // Flag token.
);
opt.resetArgs();
opt.parse(argc, argv);
vector<string*> allArgs(opt.firstArgs);
@@ -253,9 +258,10 @@ int main(int argc, const char** argv)
try
#endif
{
Machine<sgfp>(playerno, playerNames, progname, memtype, lgp, lg2,
Machine<sgfp, Share<gf2n>>(playerno, playerNames, progname, memtype, lgp, lg2,
opt.get("--direct")->isSet, opening_sum, opt.get("--parallel")->isSet,
opt.get("--threads")->isSet, max_broadcast, false).run();
opt.get("--threads")->isSet, max_broadcast, false, false,
online_opts).run();
if (server)
delete server;
@@ -268,8 +274,9 @@ int main(int argc, const char** argv)
#ifndef INSECURE
catch(...)
{
thread_info<sgfp>::purge_preprocessing(playerNames,
get_prep_dir(playerNames.num_players(), lgp, lg2));
Machine<sgfp, Share<gf2n>> machine(playerNames);
machine.live_prep = false;
thread_info<sgfp, Share<gf2n>>::purge_preprocessing(machine);
throw;
}
#endif

47
Processor/BaseMachine.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* BaseMachine.h
*
*/
#ifndef PROCESSOR_BASEMACHINE_H_
#define PROCESSOR_BASEMACHINE_H_
#include "Tools/time-func.h"
#include <map>
#include <fstream>
using namespace std;
class BaseMachine
{
protected:
static BaseMachine* singleton;
std::map<int,Timer> timer;
ifstream inpf;
void print_timers();
virtual void load_program(string threadname, string filename);
public:
string progname;
int nthreads;
static BaseMachine& s();
BaseMachine();
virtual ~BaseMachine() {}
void load_schedule(string progname);
void print_compiler();
void time();
void start(int n);
void stop(int n);
virtual void reqbl(int n) { (void)n; throw runtime_error("not defined"); }
};
#endif /* PROCESSOR_BASEMACHINE_H_ */

28
Processor/Beaver.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* Beaver.h
*
*/
#ifndef PROCESSOR_BEAVER_H_
#define PROCESSOR_BEAVER_H_
#include <vector>
using namespace std;
template<class T> class SubProcessor;
template<class T> class MAC_Check_Base;
class Player;
template<class T>
class Beaver
{
public:
Player& P;
static void muls(const vector<int>& reg, SubProcessor<T>& proc,
MAC_Check_Base<T>& MC, int size);
Beaver(Player& P) : P(P) {}
};
#endif /* PROCESSOR_BEAVER_H_ */

50
Processor/Beaver.hpp Normal file
View File

@@ -0,0 +1,50 @@
/*
* Beaver.cpp
*
*/
#include "Beaver.h"
#include <array>
template<class T>
void Beaver<T>::muls(const vector<int>& reg, SubProcessor<T>& proc, MAC_Check_Base<T>& MC,
int size)
{
assert(reg.size() % 3 == 0);
int n = reg.size() / 3;
vector<T>& shares = proc.Sh_PO;
vector<typename T::clear>& opened = proc.PO;
shares.clear();
vector<array<T, 3>> triples(n * size);
auto triple = triples.begin();
for (int i = 0; i < n; i++)
for (int j = 0; j < size; j++)
{
proc.DataF.get(DATA_TRIPLE, triple->data());
for (int k = 0; k < 2; k++)
shares.push_back(proc.S[reg[i * 3 + k + 1] + j] - (*triple)[k]);
triple++;
}
MC.POpen_Begin(opened, shares, proc.P);
MC.POpen_End(opened, shares, proc.P);
auto it = opened.begin();
triple = triples.begin();
for (int i = 0; i < n; i++)
for (int j = 0; j < size; j++)
{
typename T::clear masked[2];
T& tmp = (*triple)[2];
for (int k = 0; k < 2; k++)
{
masked[k] = *it++;
tmp += (masked[k] * (*triple)[1 - k]);
}
tmp.add(tmp, masked[0] * masked[1], proc.P.my_num(), MC.get_alphai());
proc.S[reg[i * 3] + j] = tmp;
triple++;
}
}

View File

@@ -66,9 +66,3 @@ void Binary_File_IO::read_from_file(const string filename, vector< T >& buffer,
for (unsigned int i = 0; i < buffer.size(); i++)
buffer[i].assign(&read_buffer[i*T::size()]);
}
template void Binary_File_IO::write_to_file(const string filename, const vector< Share<gfp> >& buffer);
template void Binary_File_IO::read_from_file(const string filename, vector< Share<gfp> >& buffer, const int start_posn, int &end_posn);
template void Binary_File_IO::write_to_file(const string filename, const vector< Rep3Share >& buffer);
template void Binary_File_IO::read_from_file(const string filename, vector< Rep3Share >& buffer, const int start_posn, int &end_posn);

View File

@@ -4,8 +4,6 @@
*/
#include "Buffer.h"
#include "Processor/InputTuple.h"
#include "Processor/Data_Files.h"
bool BufferBase::rewind = false;
@@ -36,7 +34,7 @@ void BufferBase::try_rewind()
{
#ifndef INSECURE
string type;
if (field_type and data_type)
if (field_type.size() and data_type.size())
type = (string)" of " + field_type + " " + data_type;
throw not_enough_to_buffer(type);
#endif
@@ -75,81 +73,3 @@ void BufferBase::purge()
file = 0;
}
}
template<class T, class U>
Buffer<T, U>::~Buffer()
{
if (timer.elapsed() && data_type)
cerr << T::type_string() << " " << data_type << " reading: "
<< timer.elapsed() << endl;
}
template<class T, class U>
void Buffer<T, U>::fill_buffer()
{
if (T::size() == sizeof(T))
{
// read directly
read((char*)buffer);
}
else
{
char read_buffer[sizeof(buffer)];
read(read_buffer);
//memset(buffer, 0, sizeof(buffer));
for (int i = 0; i < BUFFER_SIZE; i++)
buffer[i].assign(&read_buffer[i*T::size()]);
}
}
template<class T, class U>
void Buffer<T, U>::read(char* read_buffer)
{
int size_in_bytes = T::size() * BUFFER_SIZE;
int n_read = 0;
timer.start();
do
{
file->read(read_buffer + n_read, size_in_bytes - n_read);
n_read += file->gcount();
if (file->eof())
{
try_rewind();
}
if (file->fail())
{
stringstream ss;
ss << "IO problem when buffering " << T::type_string();
if (data_type)
ss << " " << data_type;
ss << " from " << filename;
throw file_error(ss.str());
}
}
while (n_read < size_in_bytes);
timer.stop();
}
template <class T, class U>
void Buffer<T,U>::input(U& a)
{
if (next == BUFFER_SIZE)
{
fill_buffer();
next = 0;
}
a = buffer[next];
next++;
}
template class Buffer< Share<gfp>, Share<gfp> >;
template class Buffer< Share<gf2n>, Share<gf2n> >;
template class Buffer< Rep3Share, Rep3Share>;
template class Buffer< InputTuple<sgfp>, RefInputTuple<sgfp> >;
template class Buffer< InputTuple<sgf2n>, RefInputTuple<sgf2n> >;
template class Buffer< InputTuple<Rep3Share>, RefInputTuple<Rep3Share> >;
template class Buffer< gfp, gfp >;
template class Buffer< gf2n, gf2n >;
template class Buffer< FixedVec<Integer, 2>, FixedVec<Integer, 2> >;
template class Buffer< Integer, Integer >;

View File

@@ -18,7 +18,6 @@ using namespace std;
#define BUFFER_SIZE 101
#endif
class BufferBase
{
protected:
@@ -26,8 +25,8 @@ protected:
ifstream* file;
int next;
const char* data_type;
const char* field_type;
string data_type;
string field_type;
Timer timer;
int tuple_length;
string filename;
@@ -35,10 +34,10 @@ protected:
public:
bool eof;
BufferBase() : file(0), next(BUFFER_SIZE), data_type(0), field_type(0),
BufferBase() : file(0), next(BUFFER_SIZE),
tuple_length(-1), eof(false) {}
void setup(ifstream* f, int length, string filename, const char* type = 0,
const char* field = 0);
void setup(ifstream* f, int length, string filename, const char* type = "",
const char* field = "");
void seekg(int pos);
bool is_up() { return file != 0; }
void try_rewind();
@@ -71,7 +70,7 @@ public:
{
}
void setup(string filename, int tuple_length, const char* data_type = 0)
void setup(string filename, int tuple_length, const char* data_type = "")
{
file = new ifstream(filename, ios::in | ios::binary);
Buffer<U, V>::setup(file, tuple_length, filename, data_type, U::type_string().c_str());
@@ -85,4 +84,73 @@ public:
}
};
template<class T, class U>
inline Buffer<T, U>::~Buffer()
{
if (timer.elapsed() && data_type.size())
cerr << T::type_string() << " " << data_type << " reading: "
<< timer.elapsed() << endl;
}
template<class T, class U>
inline void Buffer<T, U>::fill_buffer()
{
if (T::size() == sizeof(T))
{
// read directly
read((char*)buffer);
}
else
{
char read_buffer[sizeof(buffer)];
read(read_buffer);
//memset(buffer, 0, sizeof(buffer));
for (int i = 0; i < BUFFER_SIZE; i++)
buffer[i].assign(&read_buffer[i*T::size()]);
}
}
template<class T, class U>
inline void Buffer<T, U>::read(char* read_buffer)
{
int size_in_bytes = T::size() * BUFFER_SIZE;
int n_read = 0;
timer.start();
if (not file)
throw IO_Error(T::type_string() + " buffer not set up");
do
{
file->read(read_buffer + n_read, size_in_bytes - n_read);
n_read += file->gcount();
if (file->eof())
{
try_rewind();
}
if (file->fail())
{
stringstream ss;
ss << "IO problem when buffering " << T::type_string();
if (data_type.size())
ss << " " << data_type;
ss << " from " << filename;
throw file_error(ss.str());
}
}
while (n_read < size_in_bytes);
timer.stop();
}
template <class T, class U>
inline void Buffer<T,U>::input(U& a)
{
if (next == BUFFER_SIZE)
{
fill_buffer();
next = 0;
}
a = buffer[next];
next++;
}
#endif /* PROCESSOR_BUFFER_H_ */

View File

@@ -1,10 +1,17 @@
#include "Processor/Data_Files.h"
#include "Processor/Processor.h"
#include "Processor/ReplicatedPrep.h"
#include "Processor/MaliciousRepPrep.h"
#include "GC/MaliciousRepSecret.h"
#include "Math/MaliciousRep3Share.h"
#include "Processor/MaliciousRepPrep.hpp"
#include <iomanip>
#include <numeric>
const char* DataPositions::field_names[] = { "sint", "sgf2n" };
const char* DataPositions::field_names[] = { "gfp", "gf2n", "bit", "int64" };
template<>
const bool Sub_Data_Files<sgfp>::implemented[N_DTYPE] =
@@ -12,15 +19,40 @@ const bool Sub_Data_Files<sgfp>::implemented[N_DTYPE] =
;
template<>
const bool Sub_Data_Files<sgf2n>::implemented[N_DTYPE] =
const bool Sub_Data_Files<Share<gf2n>>::implemented[N_DTYPE] =
{ true, true, true, true, true, true }
;
template<>
const bool Sub_Data_Files<Rep3Share>::implemented[N_DTYPE] =
const bool Sub_Data_Files<Rep3Share<Integer>>::implemented[N_DTYPE] =
{ false, false, true, false, false, false }
;
template<>
const bool Sub_Data_Files<Rep3Share<gfp>>::implemented[N_DTYPE] =
{ true, true, true, true, false, false }
;
template<>
const bool Sub_Data_Files<Rep3Share<gf2n>>::implemented[N_DTYPE] =
{ true, true, true, true, false, false }
;
template<>
const bool Sub_Data_Files<MaliciousRep3Share<gfp>>::implemented[N_DTYPE] =
{ true, true, true, true, false, false }
;
template<>
const bool Sub_Data_Files<MaliciousRep3Share<gf2n>>::implemented[N_DTYPE] =
{ true, true, true, true, false, false }
;
template<>
const bool Sub_Data_Files<GC::MaliciousRepSecret>::implemented[N_DTYPE] =
{ true, false, true, false, false, false }
;
const int DataPositions::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 };
template<class T>
@@ -28,6 +60,58 @@ Lock Sub_Data_Files<T>::tuple_lengths_lock;
template<class T>
map<DataTag, int> Sub_Data_Files<T>::tuple_lengths;
template<>
template<>
Preprocessing<Rep3Share<gfp>>* Preprocessing<Rep3Share<gfp>>::get_new(
Machine<Rep3Share<gfp>, Rep3Share<gf2n>>& machine, DataPositions& usage)
{
if (machine.live_prep)
return new ReplicatedPrep<Rep3Share<gfp>>;
else
return new Sub_Data_Files<Rep3Share<gfp>>(machine.get_N(), machine.prep_dir_prefix, usage);
}
template<>
template<>
Preprocessing<Rep3Share<gf2n>>* Preprocessing<Rep3Share<gf2n>>::get_new(
Machine<Rep3Share<gfp>, Rep3Share<gf2n>>& machine, DataPositions& usage)
{
if (machine.live_prep)
return new ReplicatedPrep<Rep3Share<gf2n>>;
else
return new Sub_Data_Files<Rep3Share<gf2n>>(machine.get_N(), machine.prep_dir_prefix, usage);
}
template<>
template<>
Preprocessing<MaliciousRep3Share<gfp>>* Preprocessing<MaliciousRep3Share<gfp>>::get_new(
Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>& machine, DataPositions& usage)
{
if (machine.live_prep)
return new MaliciousRepPrep<gfp>;
else
return new Sub_Data_Files<MaliciousRep3Share<gfp>>(machine.get_N(), machine.prep_dir_prefix, usage);
}
template<>
template<>
Preprocessing<MaliciousRep3Share<gf2n>>* Preprocessing<MaliciousRep3Share<gf2n>>::get_new(
Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>& machine, DataPositions& usage)
{
if (machine.live_prep)
return new MaliciousRepPrep<gf2n>;
else
return new Sub_Data_Files<MaliciousRep3Share<gf2n>>(machine.get_N(), machine.prep_dir_prefix, usage);
}
template<class T>
template<class U, class V>
Preprocessing<T>* Preprocessing<T>::get_new(Machine<U, V>& machine,
DataPositions& usage)
{
return new Sub_Data_Files<T>(machine.get_N(), machine.prep_dir_prefix, usage);
}
void DataPositions::set_num_players(int num_players)
{
@@ -59,13 +143,19 @@ void DataPositions::print_cost() const
double total_cost = 0;
for (int i = 0; i < N_DATA_FIELD_TYPE; i++)
{
cerr << " Type " << field_names[i] << endl;
if (accumulate(files[i].begin(), files[i].end(), 0) > 0)
cerr << " Type " << field_names[i] << endl;
bool reading_field = true;
for (int j = 0; j < N_DTYPE; j++)
{
double cost_per_item = 0;
file >> cost_per_item;
if (reading_field)
file >> cost_per_item;
if (cost_per_item < 0)
break;
{
reading_field = false;
cost_per_item = 0;
}
long long items_used = files[i][j];
double cost = items_used * cost_per_item;
total_cost += cost;
@@ -83,7 +173,8 @@ void DataPositions::print_cost() const
}
}
cerr << "Total cost: " << total_cost << endl;
if (total_cost > 0)
cerr << "Total cost: " << total_cost << endl;
}
@@ -93,20 +184,35 @@ int Sub_Data_Files<T>::tuple_length(int dtype)
return DataPositions::tuple_size[dtype] * T::size();
}
template<class T>
string Sub_Data_Files<T>::get_suffix(int thread_num)
{
#ifdef INSECURE
(void) thread_num;
return "";
#else
if (thread_num >= 0)
return "-T" + to_string(thread_num);
else
return "";
#endif
}
template<class T>
Sub_Data_Files<T>::Sub_Data_Files(int my_num, int num_players,
const string& prep_data_dir, DataPositions& usage) :
const string& prep_data_dir, DataPositions& usage, int thread_num) :
my_num(my_num), num_players(num_players), prep_data_dir(prep_data_dir),
usage(usage)
{
cerr << "Setting up Data_Files in: " << prep_data_dir << endl;
char filename[1024];
string suffix = get_suffix(thread_num);
for (int dtype = 0; dtype < N_DTYPE; dtype++)
{
if (implemented[dtype])
{
sprintf(filename,(prep_data_dir + "%s-%s-P%d").c_str(),DataPositions::dtype_names[dtype],
string(1, T::type_char()).c_str(),my_num);
sprintf(filename,(prep_data_dir + "%s-%s-P%d%s").c_str(),DataPositions::dtype_names[dtype],
(T::type_short()).c_str(),my_num,suffix.c_str());
buffers[dtype].setup(filename,
tuple_length(dtype), DataPositions::dtype_names[dtype]);
}
@@ -115,8 +221,8 @@ Sub_Data_Files<T>::Sub_Data_Files(int my_num, int num_players,
input_buffers.resize(num_players);
for (int i=0; i<num_players; i++)
{
sprintf(filename,(prep_data_dir + "Inputs-%s-P%d-%d").c_str(),
string(1, T::type_char()).c_str(),my_num,i);
sprintf(filename,(prep_data_dir + "Inputs-%s-P%d-%d%s").c_str(),
(T::type_short()).c_str(),my_num,i,suffix.c_str());
if (i == my_num)
my_input_buffers.setup(filename,
T::size() * 3 / 2);
@@ -128,10 +234,11 @@ Sub_Data_Files<T>::Sub_Data_Files(int my_num, int num_players,
cerr << "done\n";
}
template<class sint>
Data_Files<sint>::Data_Files(int myn, int n, const string& prep_data_dir) :
usage(n), DataFp(myn, n, prep_data_dir, usage),
DataF2(myn, n, prep_data_dir, usage), prep_data_dir(prep_data_dir)
template<class sint, class sgf2n>
Data_Files<sint, sgf2n>::Data_Files(Machine<sint, sgf2n>& machine) :
usage(machine.get_N().num_players()),
DataFp(*Preprocessing<sint>::get_new(machine, usage)),
DataF2(*Preprocessing<sgf2n>::get_new(machine, usage))
{
}
@@ -168,16 +275,16 @@ void Sub_Data_Files<T>::seekg(DataPositions& pos)
}
}
template<class sint>
void Data_Files<sint>::seekg(DataPositions& pos)
template<class sint, class sgf2n>
void Data_Files<sint, sgf2n>::seekg(DataPositions& pos)
{
DataFp.seekg(pos);
DataF2.seekg(pos);
usage = pos;
}
template<class sint>
void Data_Files<sint>::skip(const DataPositions& pos)
template<class sint, class sgf2n>
void Data_Files<sint, sgf2n>::skip(const DataPositions& pos)
{
DataPositions new_pos = usage;
new_pos.increase(pos);
@@ -196,8 +303,8 @@ void Sub_Data_Files<T>::prune()
it.second.prune();
}
template<class sint>
void Data_Files<sint>::prune()
template<class sint, class sgf2n>
void Data_Files<sint, sgf2n>::prune()
{
DataFp.prune();
DataF2.prune();
@@ -215,8 +322,8 @@ void Sub_Data_Files<T>::purge()
it.second.purge();
}
template<class sint>
void Data_Files<sint>::purge()
template<class sint, class sgf2n>
void Data_Files<sint, sgf2n>::purge()
{
DataFp.purge();
DataF2.purge();
@@ -247,24 +354,31 @@ void Sub_Data_Files<T>::setup_extended(const DataTag& tag, int tuple_size)
if (!buffer.is_up())
{
stringstream ss;
ss << prep_data_dir << tag.get_string() << "-" << T::type_char() << "-P" << my_num;
ss << prep_data_dir << tag.get_string() << "-" << T::type_short() << "-P" << my_num;
extended[tag].setup(ss.str(), tuple_length);
}
}
template<class T>
void Sub_Data_Files<T>::get(SubProcessor<T>& proc, DataTag tag, const vector<int>& regs, int vector_size)
void Sub_Data_Files<T>::get(vector<T>& S, DataTag tag, const vector<int>& regs, int vector_size)
{
usage.extended[T::field_type()][tag] += vector_size;
setup_extended(tag, regs.size());
for (int j = 0; j < vector_size; j++)
for (unsigned int i = 0; i < regs.size(); i++)
extended[tag].input(proc.get_S_ref(regs[i] + j));
extended[tag].input(S[regs[i] + j]);
}
template class Sub_Data_Files<sgf2n>;
template class Sub_Data_Files<Share<gf2n>>;
template class Sub_Data_Files<sgfp>;
template class Sub_Data_Files<Rep3Share>;
template class Sub_Data_Files<Rep3Share<Integer>>;
template class Sub_Data_Files<Rep3Share<gfp>>;
template class Sub_Data_Files<Rep3Share<gf2n>>;
template class Sub_Data_Files<GC::MaliciousRepSecret>;
template class Sub_Data_Files<MaliciousRep3Share<gfp>>;
template class Sub_Data_Files<MaliciousRep3Share<gf2n>>;
template class Data_Files<sgfp>;
template class Data_Files<Rep3Share>;
template class Data_Files<sgfp, Share<gf2n>>;
template class Data_Files<Rep3Share<Integer>, Rep3Share<gf2n>>;
template class Data_Files<Rep3Share<gfp>, Rep3Share<gf2n>>;
template class Data_Files<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>;

View File

@@ -60,12 +60,39 @@ struct DataPositions
void print_cost() const;
};
template<class sint> class Processor;
template<class sint> class Data_Files;
template<class sint, class sgf2n> class Processor;
template<class sint, class sgf2n> class Data_Files;
template<class sint, class sgf2n> class Machine;
template<class T>
class Sub_Data_Files
class Preprocessing
{
public:
template<class U, class V>
static Preprocessing<T>* get_new(Machine<U, V>& machine, DataPositions& usage);
virtual ~Preprocessing() {}
virtual void set_protocol(typename T::Protocol& protocol) = 0;
virtual void seekg(DataPositions& pos) { (void) pos; }
virtual void prune() {}
virtual void purge() {}
virtual void get(Dtype dtype, T* a);
virtual void get_three(Dtype dtype, T& a, T& b, T& c) = 0;
virtual void get_two(Dtype dtype, T& a, T& b) = 0;
virtual void get_one(Dtype dtype, T& a) = 0;
virtual void get_input(T& a, typename T::clear& x, int i) = 0;
virtual void get(vector<T>& S, DataTag tag, const vector<int>& regs,
int vector_size) = 0;
};
template<class T>
class Sub_Data_Files : public Preprocessing<T>
{
template<class U> friend class Sub_Data_Files;
static const bool implemented[N_DTYPE];
static map<DataTag, int> tuple_lengths;
@@ -85,10 +112,19 @@ class Sub_Data_Files
DataPositions& usage;
public:
static string get_suffix(int thread_num);
Sub_Data_Files(int my_num, int num_players, const string& prep_data_dir,
DataPositions& usage);
DataPositions& usage, int thread_num = -1);
Sub_Data_Files(const Names& N, const string& prep_data_dir,
DataPositions& usage, int thread_num = -1) :
Sub_Data_Files(N.my_num(), N.num_players(), prep_data_dir, usage, thread_num)
{
}
~Sub_Data_Files();
void set_protocol(typename T::Protocol& protocol) { (void) protocol; }
void seekg(DataPositions& pos);
void prune();
void purge();
@@ -130,24 +166,20 @@ public:
}
void setup_extended(const DataTag& tag, int tuple_size = 0);
void get(SubProcessor<T>& proc, DataTag tag, const vector<int>& regs, int vector_size);
void get(vector<T>& S, DataTag tag, const vector<int>& regs, int vector_size);
};
template<class sint>
template<class sint, class sgf2n>
class Data_Files
{
DataPositions usage;
public:
Sub_Data_Files<sint> DataFp;
Sub_Data_Files<sgf2n> DataF2;
Preprocessing<sint>& DataFp;
Preprocessing<sgf2n>& DataF2;
const string& prep_data_dir;
Data_Files(int my_num,int n,const string& prep_data_dir);
Data_Files(Names& N, const string& prep_data_dir) :
Data_Files(N.my_num(), N.num_players(), prep_data_dir) {}
Data_Files(Machine<sint, sgf2n>& machine);
DataPositions tellg();
void seekg(DataPositions& pos);
@@ -155,64 +187,10 @@ class Data_Files
void prune();
void purge();
template<class T>
bool eof(Dtype dtype)
{
return get_sub<T>().eof(dtype);
}
template<class T>
bool input_eof(int player)
{
return get_sub<T>().input_eof(player);
}
void setup_extended(DataFieldType field_type, const DataTag& tag, int tuple_size = 0);
template<class T>
void get(SubProcessor<T>& proc, DataTag tag, const vector<int>& regs, int vector_size)
{
get_sub<T>().get(proc, tag, regs, vector_size);
}
DataPositions get_usage()
{
return usage;
}
template<class T>
Sub_Data_Files<T>& get_sub();
template <class T>
void get(Dtype dtype, T* a)
{
get_sub<T>().get(dtype, a);
}
template <class T>
void get_three(DataFieldType field_type, Dtype dtype, T& a, T& b, T& c)
{
(void)field_type;
get_sub<T>().get_three(dtype, a, b, c);
}
template <class T>
void get_two(DataFieldType field_type, Dtype dtype, T& a, T& b)
{
(void)field_type;
get_sub<T>().get_two(dtype, a, b);
}
template <class T>
void get_one(DataFieldType field_type, Dtype dtype, T& a)
{
(void)field_type;
get_sub<T>().get_one(dtype, a);
}
template <class T>
void get_input(T& a,typename T::clear& x,int i)
{
get_sub<T>().get_input(a, x, i);
}
};
template<class T> inline
@@ -236,32 +214,24 @@ inline void Sub_Data_Files<T>::get(Dtype dtype, T* a)
buffers[dtype].input(a[i]);
}
template<>
template<>
inline Sub_Data_Files<sgfp>& Data_Files<sgfp>::get_sub<sgfp>()
template<class T>
inline void Preprocessing<T>::get(Dtype dtype, T* a)
{
return DataFp;
}
template<>
template<>
inline Sub_Data_Files<sgf2n>& Data_Files<sgfp>::get_sub<sgf2n>()
{
return DataF2;
}
template<>
template<>
inline Sub_Data_Files<Rep3Share>& Data_Files<Rep3Share>::get_sub<Rep3Share>()
{
return DataFp;
}
template<>
template<>
inline Sub_Data_Files<sgf2n>& Data_Files<Rep3Share>::get_sub<sgf2n>()
{
return DataF2;
switch (dtype)
{
case DATA_TRIPLE:
get_three(dtype, a[0], a[1], a[2]);
break;
case DATA_SQUARE:
case DATA_INVERSE:
get_two(dtype, a[0], a[1]);
break;
case DATA_BIT:
get_one(dtype, a[0]);
break;
default:
throw not_implemented();
}
}
#endif

View File

@@ -8,6 +8,15 @@
class Player;
class DummyMC
{
public:
void Check(Player& P)
{
(void) P;
}
};
class DummyProtocol
{
public:

View File

@@ -1,104 +0,0 @@
/*
* Input.cpp
*
*/
#include "Input.h"
#include "Processor.h"
template<class T>
InputBase<T>::InputBase(ArithmeticProcessor& proc) :
values_input(0)
{
buffer.setup(&proc.private_input, -1, proc.private_input_filename);
}
template<class T>
Input<T>::Input(SubProcessor<Share<T>>& proc, MAC_Check<T>& mc) :
InputBase<T>(proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players())
{
}
template<class T>
InputBase<T>::~InputBase()
{
if (timer.elapsed() > 0)
cerr << T::type_string() << " inputs: " << timer.elapsed() << endl;
}
template<class T>
void Input<T>::adjust_mac(Share<T>& share, T& value)
{
T tmp;
tmp.mul(MC.get_alphai(), value);
tmp.add(share.get_mac(),tmp);
share.set_mac(tmp);
}
template<class T>
void Input<T>::start(int player, int n_inputs)
{
shares[player].resize(n_inputs);
vector<T> rr(n_inputs);
if (player == proc.P.my_num())
{
octetStream o;
for (int i = 0; i < n_inputs; i++)
{
T rr, t;
Share<T>& share = shares[player][i];
proc.DataF.get_input(share, rr, player);
T xi;
try
{
this->buffer.input(t);
}
catch (not_enough_to_buffer& e)
{
throw runtime_error("Insufficient input data to buffer");
}
t.sub(t, rr);
t.pack(o);
xi.add(t, share.get_share());
share.set_share(xi);
adjust_mac(share, t);
}
proc.P.send_all(o, true);
this->values_input += n_inputs;
}
else
{
T t;
for (int i = 0; i < n_inputs; i++)
proc.DataF.get_input(shares[player][i], t, player);
}
}
template<class T>
void Input<T>::stop(int player, vector<int> targets)
{
for (unsigned int i = 0; i < targets.size(); i++)
proc.get_S_ref(targets[i]) = shares[player][i];
if (proc.P.my_num() != player)
{
T t;
octetStream o;
this->timer.start();
proc.P.receive_player(player, o, true);
this->timer.stop();
for (unsigned int i = 0; i < targets.size(); i++)
{
Share<T>& share = proc.get_S_ref(targets[i]);
t.unpack(o);
adjust_mac(share, t);
}
}
}
template class InputBase<Integer>;
template class Input<gf2n>;
template class Input<gfp>;

View File

@@ -10,7 +10,6 @@
using namespace std;
#include "Math/Share.h"
#include "Auth/MAC_Check.h"
#include "Processor/Buffer.h"
#include "Tools/time-func.h"
@@ -20,31 +19,38 @@ template<class T>
class InputBase
{
protected:
Buffer<T,T> buffer;
Buffer<typename T::clear, typename T::clear> buffer;
Timer timer;
public:
int values_input;
static void input(SubProcessor<T>& Proc, const vector<int>& args);
InputBase(ArithmeticProcessor& proc);
~InputBase();
};
template<class T>
class Input : public InputBase<T>
class Input : public InputBase<Share<T>>
{
SubProcessor<Share<T>>& proc;
MAC_Check<T>& MC;
vector< vector< Share<T> > > shares;
octetStream o;
void adjust_mac(Share<T>& share, T& value);
public:
Input(SubProcessor<Share<T>>& proc, MAC_Check<T>& mc);
void start(int player, int n_inputs);
void stop(int player, vector<int> targets);
void reset(int player);
void add_mine(const T& input);
void add_other(int player);
void send_mine();
void start(int player, int n_inputs);
void stop(int player, const vector<int>& targets);
};
#endif /* PROCESSOR_INPUT_H_ */

173
Processor/Input.hpp Normal file
View File

@@ -0,0 +1,173 @@
/*
* Input.cpp
*
*/
#include "Input.h"
#include "Processor.h"
#include "Auth/MAC_Check.h"
template<class T>
InputBase<T>::InputBase(ArithmeticProcessor& proc) :
values_input(0)
{
buffer.setup(&proc.private_input, -1, proc.private_input_filename);
}
template<class T>
Input<T>::Input(SubProcessor<Share<T>>& proc, MAC_Check<T>& mc) :
InputBase<Share<T>>(proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players())
{
}
template<class T>
InputBase<T>::~InputBase()
{
if (timer.elapsed() > 0)
cerr << T::type_string() << " inputs: " << timer.elapsed() << endl;
}
template<class T>
void Input<T>::adjust_mac(Share<T>& share, T& value)
{
T tmp;
tmp.mul(MC.get_alphai(), value);
tmp.add(share.get_mac(),tmp);
share.set_mac(tmp);
}
template<class T>
void Input<T>::reset(int player)
{
shares[player].clear();
if (player == proc.P.my_num())
o.reset_write_head();
}
template<class T>
void Input<T>::add_mine(const T& input)
{
int player = proc.P.my_num();
T rr, t = input;
shares[player].push_back({});
Share<T>& share = shares[player].back();
proc.DataF.get_input(share, rr, player);
T xi;
t.sub(t, rr);
t.pack(o);
xi.add(t, share.get_share());
share.set_share(xi);
adjust_mac(share, t);
this->values_input++;
}
template<class T>
void Input<T>::add_other(int player)
{
T t;
shares[player].push_back({});
proc.DataF.get_input(shares[player].back(), t, player);
}
template<class T>
void Input<T>::send_mine()
{
proc.P.send_all(o, true);
}
template<class T>
void Input<T>::start(int player, int n_inputs)
{
reset(player);
if (player == proc.P.my_num())
{
for (int i = 0; i < n_inputs; i++)
{
T t;
try
{
this->buffer.input(t);
}
catch (not_enough_to_buffer& e)
{
throw runtime_error("Insufficient input data to buffer");
}
add_mine(t);
}
send_mine();
}
else
{
for (int i = 0; i < n_inputs; i++)
add_other(player);
}
}
template<class T>
void Input<T>::stop(int player, const vector<int>& targets)
{
for (unsigned int i = 0; i < targets.size(); i++)
proc.get_S_ref(targets[i]) = shares[player][i];
if (proc.P.my_num() != player)
{
T t;
octetStream o;
this->timer.start();
proc.P.receive_player(player, o, true);
this->timer.stop();
for (unsigned int i = 0; i < targets.size(); i++)
{
Share<T>& share = proc.get_S_ref(targets[i]);
t.unpack(o);
adjust_mac(share, t);
}
}
}
template<class T>
void InputBase<T>::input(SubProcessor<T>& Proc,
const vector<int>& args)
{
auto& input = Proc.input;
for (int i = 0; i < Proc.P.num_players(); i++)
input.reset(i);
assert(args.size() % 2 == 0);
int n_from_me = 0;
if (Proc.Proc.opts.interactive and Proc.Proc.thread_num == 0)
{
for (size_t i = 1; i < args.size(); i += 2)
n_from_me += (args[i] == Proc.P.my_num());
if (n_from_me > 0)
cout << "Please input " << n_from_me << " numbers:" << endl;
}
for (size_t i = 0; i < args.size(); i += 2)
{
int n = args[i + 1];
if (n == Proc.P.my_num())
{
long x = Proc.Proc.get_input(n_from_me > 0);
input.add_mine(x);
}
else
{
input.add_other(n);
}
}
if (n_from_me > 0)
cout << "Thank you" << endl;
input.send_mine();
vector<vector<int>> regs(Proc.P.num_players());
for (size_t i = 0; i < args.size(); i += 2)
{
regs[args[i + 1]].push_back(args[i]);
}
for (int i = 0; i < Proc.P.num_players(); i++)
input.stop(i, regs[i]);
}

View File

@@ -6,12 +6,20 @@
#include "Tools/time-func.h"
#include "Tools/parse.h"
#include "Auth/ReplicatedMC.h"
#include "Math/MaliciousRep3Share.h"
#include "Processor/Processor.hpp"
#include "Processor/Binary_File_IO.hpp"
#include "Processor/Input.hpp"
#include "Processor/Beaver.hpp"
#include "Auth/MaliciousRepMC.hpp"
#include <stdlib.h>
#include <algorithm>
#include <sstream>
#include <map>
#include <valgrind/callgrind.h>
#include "Tools/callgrind.h"
// broken
#undef DEBUG
@@ -223,7 +231,6 @@ void BaseInstruction::parse_operands(istream& s, int pos)
case STMS:
case LDMINT:
case STMINT:
case INPUT:
case JMPNZ:
case JMPEQZ:
case GLDI:
@@ -232,7 +239,6 @@ void BaseInstruction::parse_operands(istream& s, int pos)
case GLDMS:
case GSTMC:
case GSTMS:
case GINPUT:
case PRINTREG:
case GPRINTREG:
case LDINT:
@@ -244,6 +250,7 @@ void BaseInstruction::parse_operands(istream& s, int pos)
case GINPUTMASK:
case ACCEPTCLIENTCONNECTION:
case INV2M:
case CONDPRINTSTR:
r[0]=get_int(s);
n = get_int(s);
break;
@@ -272,6 +279,8 @@ void BaseInstruction::parse_operands(istream& s, int pos)
case GOPEN:
case MULS:
case GMULS:
case INPUT:
case GINPUT:
num_var_args = get_int(s);
get_vector(num_var_args, start, s);
break;
@@ -360,7 +369,9 @@ void BaseInstruction::parse_operands(istream& s, int pos)
break;
default:
ostringstream os;
os << "Invalid instruction " << hex << showbase << opcode << " at " << dec << pos;
os << "Invalid instruction " << hex << showbase << opcode << " at " << dec << pos << endl;
os << "This virtual machine executes arithmetic circuits only." << endl;
os << "Try compiling without '-B' and don't use sbit* types." << endl;
throw Invalid_Instruction(os.str());
}
}
@@ -431,17 +442,29 @@ int BaseInstruction::get_reg_type() const
}
}
int BaseInstruction::get_max_reg(int reg_type) const
unsigned BaseInstruction::get_max_reg(int reg_type) const
{
if (get_reg_type() != reg_type) { return 0; }
const int *begin, *end;
if (start.size())
return *max_element(start.begin(), start.end()) + size;
{
begin = start.data();
end = start.data() + start.size();
}
else
return *max_element(r, r + 3) + size;
{
begin = r;
end = r + 3;
}
unsigned res = 0;
for (auto it = begin; it != end; it++)
res = max(res, (unsigned)*it);
return res + size;
}
int Instruction::get_mem(RegType reg_type, SecrecyType sec_type) const
unsigned Instruction::get_mem(RegType reg_type, SecrecyType sec_type) const
{
if (get_reg_type() == reg_type and is_direct_memory_access(sec_type))
return n + size;
@@ -498,13 +521,15 @@ ostream& operator<<(ostream& s,const Instruction& instr)
}
template<class sint>
template<class sint, class sgf2n>
#ifndef __clang__
__attribute__((always_inline))
#endif
inline void Instruction::execute(Processor<sint>& Proc) const
inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
{
Proc.PC+=1;
auto& Procp = Proc.Procp;
auto& Proc2 = Proc.Proc2;
#ifndef DEBUG
// optimize some instructions
@@ -560,12 +585,12 @@ inline void Instruction::execute(Processor<sint>& Proc) const
return;
case TRIPLE:
for (int i = 0; i < size; i++)
Proc.DataF.get_three(DATA_MODP, DATA_TRIPLE, Proc.get_Sp_ref(r[0] + i),
Procp.DataF.get_three(DATA_TRIPLE, Proc.get_Sp_ref(r[0] + i),
Proc.get_Sp_ref(r[1] + i), Proc.get_Sp_ref(r[2] + i));
return;
case BIT:
for (int i = 0; i < size; i++)
Proc.DataF.get_one(DATA_MODP, DATA_BIT, Proc.get_Sp_ref(r[0] + i));
Procp.DataF.get_one(DATA_BIT, Proc.get_Sp_ref(r[0] + i));
return;
}
#endif
@@ -586,15 +611,7 @@ inline void Instruction::execute(Processor<sint>& Proc) const
Proc.get_Sp_ref(r[0]).assign(n, Proc.P.my_num(), Proc.MCp.get_alphai());
break;
case GLDSI:
{ Proc.temp.ans2.assign(n);
if (Proc.P.my_num()==0)
Proc.get_S2_ref(r[0]).set_share(Proc.temp.ans2);
else
Proc.get_S2_ref(r[0]).assign_zero();
gf2n& tmp=Proc.temp.tmp2;
tmp.mul(Proc.MC2.get_alphai(),Proc.temp.ans2);
Proc.get_S2_ref(r[0]).set_mac(tmp);
}
Proc.get_S2_ref(r[0]).assign(n, Proc.P.my_num(), Proc.MC2.get_alphai());
break;
case LDMC:
Proc.write_Cp(r[0],Proc.machine.Mp.read_C(n));
@@ -1085,86 +1102,62 @@ inline void Instruction::execute(Processor<sint>& Proc) const
#endif
break;
case TRIPLE:
Proc.DataF.get_three(DATA_MODP, DATA_TRIPLE, Proc.get_Sp_ref(r[0]),Proc.get_Sp_ref(r[1]),Proc.get_Sp_ref(r[2]));
Procp.DataF.get_three(DATA_TRIPLE, Proc.get_Sp_ref(r[0]),Proc.get_Sp_ref(r[1]),Proc.get_Sp_ref(r[2]));
break;
case GTRIPLE:
Proc.DataF.get_three(DATA_GF2N, DATA_TRIPLE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]),Proc.get_S2_ref(r[2]));
Proc2.DataF.get_three(DATA_TRIPLE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]),Proc.get_S2_ref(r[2]));
break;
case GBITTRIPLE:
Proc.DataF.get_three(DATA_GF2N, DATA_BITTRIPLE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]),Proc.get_S2_ref(r[2]));
Proc2.DataF.get_three(DATA_BITTRIPLE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]),Proc.get_S2_ref(r[2]));
break;
case GBITGF2NTRIPLE:
Proc.DataF.get_three(DATA_GF2N, DATA_BITGF2NTRIPLE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]),Proc.get_S2_ref(r[2]));
Proc2.DataF.get_three(DATA_BITGF2NTRIPLE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]),Proc.get_S2_ref(r[2]));
break;
case SQUARE:
Proc.DataF.get_two(DATA_MODP, DATA_SQUARE, Proc.get_Sp_ref(r[0]),Proc.get_Sp_ref(r[1]));
Procp.DataF.get_two(DATA_SQUARE, Proc.get_Sp_ref(r[0]),Proc.get_Sp_ref(r[1]));
break;
case GSQUARE:
Proc.DataF.get_two(DATA_GF2N, DATA_SQUARE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]));
Proc2.DataF.get_two(DATA_SQUARE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]));
break;
case BIT:
Proc.DataF.get_one(DATA_MODP, DATA_BIT, Proc.get_Sp_ref(r[0]));
Procp.DataF.get_one(DATA_BIT, Proc.get_Sp_ref(r[0]));
break;
case GBIT:
Proc.DataF.get_one(DATA_GF2N, DATA_BIT, Proc.get_S2_ref(r[0]));
Proc2.DataF.get_one(DATA_BIT, Proc.get_S2_ref(r[0]));
break;
case INV:
Proc.DataF.get_two(DATA_MODP, DATA_INVERSE, Proc.get_Sp_ref(r[0]),Proc.get_Sp_ref(r[1]));
Procp.DataF.get_two(DATA_INVERSE, Proc.get_Sp_ref(r[0]),Proc.get_Sp_ref(r[1]));
break;
case GINV:
Proc.DataF.get_two(DATA_GF2N, DATA_INVERSE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]));
Proc2.DataF.get_two(DATA_INVERSE, Proc.get_S2_ref(r[0]),Proc.get_S2_ref(r[1]));
break;
case INPUTMASK:
Proc.DataF.get_input(Proc.get_Sp_ref(r[0]), Proc.temp.rrp, n);
Procp.DataF.get_input(Proc.get_Sp_ref(r[0]), Proc.temp.rrp, n);
if (n == Proc.P.my_num())
Proc.temp.rrp.output(Proc.private_output, false);
break;
case GINPUTMASK:
Proc.DataF.get_input(Proc.get_S2_ref(r[0]), Proc.temp.ans2, n);
Proc2.DataF.get_input(Proc.get_S2_ref(r[0]), Proc.temp.ans2, n);
if (n == Proc.P.my_num())
Proc.temp.ans2.output(Proc.private_output, false);
break;
case INPUT:
sint::Protocol::input(Proc.Procp, n, r);
sint::Input::input(Proc.Procp, start);
break;
case GINPUT:
{ gf2n& rr=Proc.temp.rr2; gf2n& t=Proc.temp.t2; gf2n& tmp=Proc.temp.tmp2;
Proc.DataF.get_input(Proc.get_S2_ref(r[0]),rr,n);
octetStream o;
if (n==Proc.P.my_num())
{ gf2n& xi=Proc.temp.xi2;
#ifdef DEBUG
printf("Enter your input : \n");
#endif
word x;
cin >> x;
t.assign(x);
t.sub(t,rr);
t.pack(o);
Proc.P.send_all(o);
xi.add(t,Proc.get_S2_ref(r[0]).get_share());
Proc.get_S2_ref(r[0]).set_share(xi);
}
else
{ Proc.P.receive_player(n,o);
t.unpack(o);
}
tmp.mul(Proc.MC2.get_alphai(),t);
tmp.add(Proc.get_S2_ref(r[0]).get_mac(),tmp);
Proc.get_S2_ref(r[0]).set_mac(tmp);
}
sgf2n::Input::input(Proc.Proc2, start);
break;
case STARTINPUT:
Proc.inputp.start(r[0],n);
Proc.Procp.input.start(r[0],n);
break;
case GSTARTINPUT:
Proc.input2.start(r[0],n);
Proc.Proc2.input.start(r[0],n);
break;
case STOPINPUT:
Proc.inputp.stop(n,start);
Proc.Procp.input.stop(n,start);
break;
case GSTOPINPUT:
Proc.input2.stop(n,start);
Proc.Proc2.input.stop(n,start);
break;
case ANDC:
#ifdef DEBUG
@@ -1382,7 +1375,7 @@ inline void Instruction::execute(Processor<sint>& Proc) const
Proc.Procp.protocol.muls(start, Proc.Procp, Proc.MCp, size);
return;
case GMULS:
SPDZ<gf2n>::muls(start, Proc.Proc2, Proc.MC2, size);
Proc.Proc2.protocol.muls(start, Proc.Proc2, Proc.MC2, size);
return;
case JMP:
Proc.PC += (signed int) n;
@@ -1466,92 +1459,72 @@ inline void Instruction::execute(Processor<sint>& Proc) const
Proc.write_Ci(r[0], Proc.read_C2(r[1]).get_word());
break;
case PRINTMEM:
if (Proc.P.my_num() == 0)
{ cout << "Mem[" << r[0] << "] = " << Proc.machine.Mp.read_C(r[0]) << endl; }
{ Proc.out << "Mem[" << r[0] << "] = " << Proc.machine.Mp.read_C(r[0]) << endl; }
break;
case GPRINTMEM:
if (Proc.P.my_num() == 0)
{ cout << "Mem[" << r[0] << "] = " << Proc.machine.M2.read_C(r[0]) << endl; }
{ Proc.out << "Mem[" << r[0] << "] = " << Proc.machine.M2.read_C(r[0]) << endl; }
break;
case PRINTREG:
if (Proc.P.my_num() == 0)
{
cout << "Reg[" << r[0] << "] = " << Proc.read_Cp(r[0])
Proc.out << "Reg[" << r[0] << "] = " << Proc.read_Cp(r[0])
<< " # " << string((char*)&n,sizeof(n)) << endl;
}
break;
case GPRINTREG:
if (Proc.P.my_num() == 0)
{
cout << "Reg[" << r[0] << "] = " << Proc.read_C2(r[0])
Proc.out << "Reg[" << r[0] << "] = " << Proc.read_C2(r[0])
<< " # " << string((char*)&n,sizeof(n)) << endl;
}
break;
case PRINTREGPLAIN:
if (Proc.P.my_num() == 0)
{
cout << Proc.read_Cp(r[0]) << flush;
Proc.out << Proc.read_Cp(r[0]) << flush;
}
break;
case GPRINTREGPLAIN:
if (Proc.P.my_num() == 0)
{
cout << Proc.read_C2(r[0]) << flush;
Proc.out << Proc.read_C2(r[0]) << flush;
}
break;
case PRINTINT:
if (Proc.P.my_num() == 0)
{
cout << Proc.read_Ci(r[0]) << flush;
Proc.out << Proc.read_Ci(r[0]) << flush;
}
break;
case PRINTFLOATPLAIN:
if (Proc.P.my_num() == 0)
{
typename sint::clear v = Proc.read_Cp(start[0]);
typename sint::clear p = Proc.read_Cp(start[1]);
typename sint::clear z = Proc.read_Cp(start[2]);
typename sint::clear s = Proc.read_Cp(start[3]);
to_bigint(Proc.temp.aa, v);
// MPIR can't handle more precision in exponent
to_signed_bigint(Proc.temp.aa2, p, 31);
long exp = Proc.temp.aa2.get_si();
mpf_class res = Proc.temp.aa;
if (exp > 0)
mpf_mul_2exp(res.get_mpf_t(), res.get_mpf_t(), exp);
else
mpf_div_2exp(res.get_mpf_t(), res.get_mpf_t(), -exp);
if (z.is_one())
res = 0;
if (!s.is_zero())
res *= -1;
if (not z.is_bit() or not s.is_bit())
throw Processor_Error("invalid floating point number");
cout << res << flush;
Proc.out << bigint::get_float(v, exp, z, s) << flush;
}
break;
case PRINTSTR:
if (Proc.P.my_num() == 0)
{
cout << string((char*)&n,sizeof(n)) << flush;
Proc.out << string((char*)&n,sizeof(n)) << flush;
}
break;
case CONDPRINTSTR:
if (not Proc.read_Cp(r[0]).is_zero())
Proc.out << string((char*)&n,sizeof(n)) << flush;
break;
case PRINTCHR:
if (Proc.P.my_num() == 0)
{
cout << string((char*)&n,1) << flush;
Proc.out << string((char*)&n,1) << flush;
}
break;
case PRINTCHRINT:
if (Proc.P.my_num() == 0)
{
cout << string((char*)&(Proc.read_Ci(r[0])),1) << flush;
Proc.out << string((char*)&(Proc.read_Ci(r[0])),1) << flush;
}
break;
case PRINTSTRINT:
if (Proc.P.my_num() == 0)
{
cout << string((char*)&(Proc.read_Ci(r[0])),sizeof(int)) << flush;
Proc.out << string((char*)&(Proc.read_Ci(r[0])),sizeof(int)) << flush;
}
break;
case RAND:
@@ -1688,10 +1661,10 @@ inline void Instruction::execute(Processor<sint>& Proc) const
Proc.privateOutput2.stop(n,r[0]);
break;
case PREP:
Proc.DataF.get(Proc.Procp, r, start, size);
Procp.DataF.get(Proc.Procp.get_S(), r, start, size);
return;
case GPREP:
Proc.DataF.get(Proc.Proc2, r, start, size);
Proc2.DataF.get(Proc.Proc2.get_S(), r, start, size);
return;
default:
printf("Case of opcode=%d not implemented yet\n",opcode);
@@ -1705,8 +1678,8 @@ inline void Instruction::execute(Processor<sint>& Proc) const
}
}
template<class sint>
void Program::execute(Processor<sint>& Proc) const
template<class sint, class sgf2n>
void Program::execute(Processor<sint, sgf2n>& Proc) const
{
unsigned int size = p.size();
Proc.PC=0;
@@ -1717,5 +1690,7 @@ void Program::execute(Processor<sint>& Proc) const
{ p[Proc.PC].execute(Proc); }
}
template void Program::execute(Processor<sgfp>& Proc) const;
template void Program::execute(Processor<Rep3Share>& Proc) const;
template void Program::execute(Processor<sgfp, Share<gf2n>>& Proc) const;
template void Program::execute(Processor<Rep3Share<Integer>, Rep3Share<gf2n>>& Proc) const;
template void Program::execute(Processor<Rep3Share<gfp>, Rep3Share<gf2n>>& Proc) const;
template void Program::execute(Processor<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>& Proc) const;

View File

@@ -9,13 +9,12 @@
#include <vector>
using namespace std;
#include "Processor/Data_Files.h"
#include "Networking/Player.h"
#include "Math/Integer.h"
#include "Auth/MAC_Check.h"
#include "Math/Share.h"
template<class sint> class Machine;
template<class sint> class Processor;
template<class sint, class sgf2n> class Machine;
template<class sint, class sgf2n> class Processor;
/*
* Opcode constants
@@ -166,6 +165,7 @@ enum
PRINTFLOATPLAIN = 0xBC,
WRITEFILESHARE = 0xBD,
READFILESHARE = 0xBE,
CONDPRINTSTR = 0xBF,
// GF(2^n) versions
@@ -272,7 +272,7 @@ enum SecrecyType {
MAX_SECRECY_TYPE
};
template<class sint>
template<class sint, class sgf2n>
struct TempVars {
gf2n ans2; Share<gf2n> Sans2;
typename sint::clear ansp;
@@ -312,9 +312,10 @@ public:
bool is_direct_memory_access(SecrecyType sec_type) const;
// Returns the maximal register used
int get_max_reg(int reg_type) const;
unsigned get_max_reg(int reg_type) const;
};
struct DataPositions;
class Instruction : public BaseInstruction
{
@@ -326,14 +327,14 @@ public:
bool get_offline_data_usage(DataPositions& usage);
// Returns the memory size used if applicable and known
int get_mem(RegType reg_type, SecrecyType sec_type) const;
unsigned get_mem(RegType reg_type, SecrecyType sec_type) const;
friend ostream& operator<<(ostream& s,const Instruction& instr);
// Execute this instruction, updateing the processor and memory
// and streams pointing to the triples etc
template<class sint>
void execute(Processor<sint>& Proc) const;
template<class sint, class sgf2n>
void execute(Processor<sint, sgf2n>& Proc) const;
};

View File

@@ -1,10 +1,14 @@
#include "Machine.h"
#include "Memory.hpp"
#include "Online-Thread.hpp"
#include "Exceptions/Exceptions.h"
#include <sys/time.h>
#include "Math/Setup.h"
#include "Math/MaliciousRep3Share.h"
#include <iostream>
#include <vector>
@@ -31,15 +35,15 @@ BaseMachine::BaseMachine() : nthreads(0)
singleton = this;
}
template<class sint>
Machine<sint>::Machine(int my_number, Names& playerNames,
template<class sint, class sgf2n>
Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
string progname_str, string memtype, int lgp, int lg2, bool direct,
int opening_sum, bool parallel, bool receive_threads, int max_broadcast,
bool use_encryption)
bool use_encryption, bool live_prep, OnlineOptions opts)
: my_number(my_number), N(playerNames), tn(0), numt(0), usage_unknown(false),
direct(direct), opening_sum(opening_sum), parallel(parallel),
receive_threads(receive_threads), max_broadcast(max_broadcast),
use_encryption(use_encryption)
use_encryption(use_encryption), live_prep(live_prep), opts(opts)
{
if (opening_sum < 2)
this->opening_sum = N.num_players();
@@ -86,8 +90,7 @@ Machine<sint>::Machine(int my_number, Names& playerNames,
}
else if (memtype.compare("old")==0)
{
sprintf(filename, PREP_DIR "Memory-P%d", my_number);
inpf.open(filename,ios::in | ios::binary);
inpf.open(memory_filename(), ios::in | ios::binary);
if (inpf.fail()) { throw file_error(); }
inpf >> M2 >> Mp >> Mi;
inpf.close();
@@ -126,7 +129,7 @@ Machine<sint>::Machine(int my_number, Names& playerNames,
tinfo[i].machine=this;
// lock for synchronization
pthread_mutex_lock(&t_mutex[i]);
pthread_create(&threads[i],NULL,thread_info<sint>::Main_Func,&tinfo[i]);
pthread_create(&threads[i],NULL,thread_info<sint, sgf2n>::Main_Func,&tinfo[i]);
}
// synchronize with clients before starting timer
@@ -177,8 +180,8 @@ void BaseMachine::print_compiler()
inpf.close();
}
template<class sint>
void Machine<sint>::load_program(string threadname, string filename)
template<class sint, class sgf2n>
void Machine<sint, sgf2n>::load_program(string threadname, string filename)
{
ifstream pinp(filename);
if (pinp.fail()) { throw file_error(filename); }
@@ -191,8 +194,8 @@ void Machine<sint>::load_program(string threadname, string filename)
Mi.minimum_size(INT, progs[i], threadname);
}
template<class sint>
DataPositions Machine<sint>::run_tape(int thread_number, int tape_number, int arg, int line_number)
template<class sint, class sgf2n>
DataPositions Machine<sint, sgf2n>::run_tape(int thread_number, int tape_number, int arg, int line_number)
{
if (thread_number >= (int)tinfo.size())
throw Processor_Error("invalid thread number: " + to_string(thread_number) + "/" + to_string(tinfo.size()));
@@ -231,8 +234,8 @@ DataPositions Machine<sint>::run_tape(int thread_number, int tape_number, int ar
}
}
template<class sint>
void Machine<sint>::join_tape(int i)
template<class sint, class sgf2n>
void Machine<sint, sgf2n>::join_tape(int i)
{
join_timer[i].start();
pthread_mutex_lock(&t_mutex[i]);
@@ -243,8 +246,8 @@ void Machine<sint>::join_tape(int i)
join_timer[i].stop();
}
template<class sint>
void Machine<sint>::run()
template<class sint, class sgf2n>
void Machine<sint, sgf2n>::run()
{
Timer proc_timer(CLOCK_PROCESS_CPUTIME_ID);
proc_timer.start();
@@ -332,16 +335,14 @@ void Machine<sint>::run()
cerr << "Full broadcast" << endl;
// Reduce memory size to speed up
int max_size = 1 << 20;
unsigned max_size = 1 << 20;
if (M2.size_s() > max_size)
M2.resize_s(max_size);
if (Mp.size_s() > max_size)
Mp.resize_s(max_size);
// Write out the memory to use next time
char filename[1024];
sprintf(filename,PREP_DIR "Memory-P%d",my_number);
ofstream outf(filename,ios::out | ios::binary);
ofstream outf(memory_filename(), ios::out | ios::binary);
outf << M2 << Mp << Mi;
outf.close();
@@ -370,7 +371,7 @@ void Machine<sint>::run()
pos.print_cost();
#ifndef INSECURE
Data_Files<sint> df(N.my_num(), N.num_players(), prep_dir_prefix);
Data_Files<sint, sgf2n> df(*this);
df.seekg(pos);
df.prune();
#endif
@@ -378,6 +379,12 @@ void Machine<sint>::run()
cerr << "End of prog" << endl;
}
template<class sint, class sgf2n>
string Machine<sint, sgf2n>::memory_filename()
{
return PREP_DIR "Memory-" + sint::type_short() + "-P" + to_string(my_number);
}
void BaseMachine::load_program(string threadname, string filename)
{
(void)threadname;
@@ -411,11 +418,13 @@ void BaseMachine::print_timers()
cerr << "Time" << it->first << " = " << it->second.elapsed() << " seconds " << endl;
}
template<class sint>
void Machine<sint>::reqbl(int n)
template<class sint, class sgf2n>
void Machine<sint, sgf2n>::reqbl(int n)
{
sint::Protocol::reqbl(n);
sint::clear::reqbl(n);
}
template class Machine<sgfp>;
template class Machine<Rep3Share>;
template class Machine<sgfp, Share<gf2n>>;
template class Machine<Rep3Share<Integer>, Rep3Share<gf2n>>;
template class Machine<Rep3Share<gfp>, Rep3Share<gf2n>>;
template class Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>;

View File

@@ -6,11 +6,12 @@
#ifndef MACHINE_H_
#define MACHINE_H_
#include "Processor/BaseMachine.h"
#include "Processor/Memory.h"
#include "Processor/Program.h"
#include "Processor/OnlineOptions.h"
#include "Processor/Online-Thread.h"
#include "Processor/Data_Files.h"
#include "Math/gfp.h"
#include "Tools/time-func.h"
@@ -19,39 +20,7 @@
#include <map>
using namespace std;
class BaseMachine
{
protected:
static BaseMachine* singleton;
std::map<int,Timer> timer;
ifstream inpf;
void print_timers();
virtual void load_program(string threadname, string filename);
public:
string progname;
int nthreads;
static BaseMachine& s();
BaseMachine();
virtual ~BaseMachine() {}
void load_schedule(string progname);
void print_compiler();
void time();
void start(int n);
void stop(int n);
virtual void reqbl(int n) { (void)n; }
};
template<class sint>
template<class sint, class sgf2n>
class Machine : public BaseMachine
{
/* The mutex's lock the C-threads and then only release
@@ -60,12 +29,12 @@ class Machine : public BaseMachine
* MPC thread releases the mutex
*/
vector<thread_info<sint>> tinfo;
vector<thread_info<sint, sgf2n>> tinfo;
vector<pthread_t> threads;
int my_number;
Names& N;
gfp alphapi;
typename sint::value_type alphapi;
gf2n alpha2i;
// Keep record of used offline data
@@ -98,17 +67,25 @@ class Machine : public BaseMachine
bool receive_threads;
int max_broadcast;
bool use_encryption;
bool live_prep;
OnlineOptions opts;
Machine(int my_number, Names& playerNames, string progname,
string memtype, int lgp, int lg2, bool direct, int opening_sum, bool parallel,
bool receive_threads, int max_broadcast, bool use_encryption);
bool receive_threads, int max_broadcast, bool use_encryption, bool live_prep,
OnlineOptions opts);
const Names& get_N() { return N; }
DataPositions run_tape(int thread_number, int tape_number, int arg, int line_number);
void join_tape(int thread_number);
void run();
string memory_filename();
// Only for Player-Demo.cpp
Machine(): N(*(new Names())) {}
Machine(Names& N = *(new Names())): N(N) {}
void reqbl(int n);
};

View File

@@ -0,0 +1,47 @@
/*
* MaliciousRepPrep.h
*
*/
#ifndef PROCESSOR_MALICIOUSREPPREP_H_
#define PROCESSOR_MALICIOUSREPPREP_H_
#include "Data_Files.h"
#include "ReplicatedPrep.h"
#include "Math/MaliciousRep3Share.h"
#include "Auth/MaliciousRepMC.h"
#include <array>
template<class U>
class MaliciousRepPrep : public BufferPrep<MaliciousRep3Share<U>>
{
typedef MaliciousRep3Share<U> T;
typedef BufferPrep<MaliciousRep3Share<U>> super;
ReplicatedPrep<Rep3Share<U>> honest_prep;
Replicated<Rep3Share<U>>* replicated;
HashMaliciousRepMC<T> MC;
vector<T> masked;
vector<T> checks;
vector <typename T::clear> opened;
vector<array<T, 3>> check_triples;
vector<array<T, 2>> check_squares;
void clear_tmp();
void buffer_triples();
void buffer_squares();
void buffer_inverses();
void buffer_bits();
public:
MaliciousRepPrep();
~MaliciousRepPrep();
void set_protocol(Beaver<T>& protocol);
};
#endif /* PROCESSOR_MALICIOUSREPPREP_H_ */

View File

@@ -0,0 +1,165 @@
/*
* MaliciousRepPrep.cpp
*
*/
#include "MaliciousRepPrep.h"
#include "Auth/Subroutines.h"
#include "Auth/MaliciousRepMC.hpp"
template<class U>
MaliciousRepPrep<U>::MaliciousRepPrep() : replicated(0)
{
}
template<class U>
MaliciousRepPrep<U>::~MaliciousRepPrep()
{
if (replicated)
delete replicated;
}
template<class U>
void MaliciousRepPrep<U>::set_protocol(Beaver<T>& protocol)
{
replicated = new Replicated<Rep3Share<U>>(protocol.P);
honest_prep.set_protocol(*replicated);
}
template<class U>
void MaliciousRepPrep<U>::clear_tmp()
{
masked.clear();
checks.clear();
check_triples.clear();
check_squares.clear();
}
template<class U>
void MaliciousRepPrep<U>::buffer_triples()
{
auto& triples = this->triples;
auto& buffer_size = this->buffer_size;
clear_tmp();
Player& P = honest_prep.protocol->P;
triples.clear();
for (int i = 0; i < buffer_size; i++)
{
T a, b, c;
T f, g, h;
honest_prep.get_three(DATA_TRIPLE, a, b, c);
honest_prep.get_three(DATA_TRIPLE, f, g, h);
triples.push_back({a, b, c});
check_triples.push_back({f, g, h});
}
auto t = Create_Random<typename T::clear>(P);
for (int i = 0; i < buffer_size; i++)
{
T& a = triples[i][0];
T& b = triples[i][1];
T& f = check_triples[i][0];
T& g = check_triples[i][1];
masked.push_back(a * t - f);
masked.push_back(b - g);
}
MC.POpen(opened, masked, P);
for (int i = 0; i < buffer_size; i++)
{
T& b = triples[i][1];
T& c = triples[i][2];
T& f = check_triples[i][0];
T& h = check_triples[i][2];
typename T::clear& rho = opened[2 * i];
typename T::clear& sigma = opened[2 * i + 1];
checks.push_back(t * c - h - rho * b - sigma * f);
}
MC.POpen(opened, checks, P);
for (auto& check : opened)
if (check != 0)
throw Offline_Check_Error("triple");
MC.Check(P);
}
template<class U>
void MaliciousRepPrep<U>::buffer_squares()
{
auto& squares = this->squares;
auto& buffer_size = this->buffer_size;
clear_tmp();
Player& P = honest_prep.protocol->P;
squares.clear();
for (int i = 0; i < buffer_size; i++)
{
T a, b;
T f, h;
honest_prep.get_two(DATA_SQUARE, a, b);
honest_prep.get_two(DATA_SQUARE, f, h);
squares.push_back({a, b});
check_squares.push_back({f, h});
}
auto t = Create_Random<typename T::clear>(P);
for (int i = 0; i < buffer_size; i++)
{
T& a = squares[i][0];
T& f = check_squares[i][0];
masked.push_back(a * t - f);
}
MC.POpen(opened, masked, P);
for (int i = 0; i < buffer_size; i++)
{
T& a = squares[i][0];
T& b = squares[i][1];
T& f = check_squares[i][0];
T& h = check_squares[i][1];
auto& rho = opened[i];
checks.push_back(t * t * b - h - rho * (t * a + f));
}
MC.POpen(opened, checks, P);
for (auto& check : opened)
if (check != 0)
throw Offline_Check_Error("square");
}
template<class U>
void MaliciousRepPrep<U>::buffer_inverses()
{
BufferPrep<T>::buffer_inverses(MC, honest_prep.protocol->P);
}
template<class U>
void MaliciousRepPrep<U>::buffer_bits()
{
auto& bits = this->bits;
auto& buffer_size = this->buffer_size;
clear_tmp();
Player& P = honest_prep.protocol->P;
bits.clear();
for (int i = 0; i < buffer_size; i++)
{
T a, f, h;
honest_prep.get_one(DATA_BIT, a);
honest_prep.get_two(DATA_SQUARE, f, h);
bits.push_back(a);
check_squares.push_back({f, h});
}
auto t = Create_Random<typename T::clear>(P);
for (int i = 0; i < buffer_size; i++)
{
T& a = bits[i];
T& f = check_squares[i][0];
masked.push_back(t * a - f);
}
MC.POpen(opened, masked, P);
for (int i = 0; i < buffer_size; i++)
{
T& a = bits[i];
T& f = check_squares[i][0];
T& h = check_squares[i][1];
auto& rho = opened[i];
masked.push_back(t * t * a - h - rho * (t * a + f));
}
MC.POpen(opened, checks, P);
for (auto& check : opened)
if (check != 0)
throw Offline_Check_Error("bit");
}

View File

@@ -31,9 +31,9 @@ class Memory
void resize_c(int sz)
{ MC.resize(sz); }
int size_s()
unsigned size_s()
{ return MS.size(); }
int size_c()
unsigned size_c()
{ return MC.size(); }
const typename T::clear& read_C(int i) const

View File

@@ -9,7 +9,7 @@
template<class T>
void Memory<T>::minimum_size(RegType reg_type, const Program& program, string threadname)
{
const int* sizes = program.direct_mem(reg_type);
const unsigned* sizes = program.direct_mem(reg_type);
if (sizes[SECRET] > size_s())
{
cerr << threadname << " needs more secret " << T::type_string() << " memory, resizing to "
@@ -141,18 +141,3 @@ void Memory<T>::Load_Memory(ifstream& inpf)
S.input(inpf,true);
}
}
template class Memory<sgfp>;
template class Memory<sgf2n>;
template class Memory<Integer>;
template class Memory<Rep3Share>;
template istream& operator>>(istream& s,Memory<sgfp>& M);
template istream& operator>>(istream& s,Memory<sgf2n>& M);
template istream& operator>>(istream& s,Memory<Integer>& M);
template istream& operator>>(istream& s,Memory<Rep3Share>& M);
template ostream& operator<<(ostream& s,const Memory<sgfp>& M);
template ostream& operator<<(ostream& s,const Memory<sgf2n>& M);
template ostream& operator<<(ostream& s,const Memory<Integer>& M);
template ostream& operator<<(ostream& s,const Memory<Rep3Share>& M);

View File

@@ -10,9 +10,9 @@
#include <vector>
using namespace std;
template<class sint> class Machine;
template<class sint, class sgf2n> class Machine;
template<class sint>
template<class sint, class sgf2n>
class thread_info
{
public:
@@ -21,7 +21,7 @@ class thread_info
int covert;
Names* Nms;
gf2n *alpha2i;
gfp *alphapi;
typename sint::value_type *alphapi;
int prognum;
bool finished;
bool ready;
@@ -31,11 +31,11 @@ class thread_info
// Integer arg (optional)
int arg;
Machine<sint>* machine;
Machine<sint, sgf2n>* machine;
static void* Main_Func(void *ptr);
static void purge_preprocessing(Names& N, string prep_dir);
static void purge_preprocessing(Machine<sint, sgf2n>& machine);
};
#endif

Some files were not shown because too many files have changed in this diff Show More