mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-01-07 20:53:55 -05:00
Optimized matrix multiplication; data type for quantization.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -62,6 +62,7 @@ Programs/Public-Input/*
|
||||
*.a
|
||||
*.static
|
||||
*.d
|
||||
local/
|
||||
|
||||
# Packages #
|
||||
############
|
||||
|
||||
@@ -466,3 +466,5 @@ template class MAC_Check_Base<ShamirShare<gfp>>;
|
||||
template class MAC_Check_Base<ShamirShare<gf2n>>;
|
||||
template class MAC_Check_Base<MaliciousShamirShare<gfp>>;
|
||||
template class MAC_Check_Base<MaliciousShamirShare<gf2n>>;
|
||||
template class MAC_Check_Base<Share<gfp>>;
|
||||
template class MAC_Check_Base<Share<gf2n>>;
|
||||
|
||||
@@ -85,14 +85,15 @@ void CommMaliciousRepMC<T>::POpen_Begin(vector<typename T::clear>& values,
|
||||
for (auto& x : S)
|
||||
for (int i = 0; i < 2; i++)
|
||||
x[i].pack(os[1 - i]);
|
||||
P.send_relative(os);
|
||||
P.pass_around(os[0], 1);
|
||||
P.pass_around(os[1], 2);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void CommMaliciousRepMC<T>::POpen_End(vector<typename T::clear>& values,
|
||||
const vector<T>& S, const Player& P)
|
||||
{
|
||||
P.receive_relative(os);
|
||||
(void) P;
|
||||
if (os[0] != os[1])
|
||||
throw mac_fail();
|
||||
values.clear();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
#include "MaliciousShamirMC.h"
|
||||
#include "Processor/ShamirMachine.h"
|
||||
#include "Machines/ShamirMachine.h"
|
||||
|
||||
template<class T>
|
||||
MaliciousShamirMC<T>::MaliciousShamirMC()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "MAC_Check.h"
|
||||
#include "Math/ShamirShare.h"
|
||||
#include "Processor/ShamirMachine.h"
|
||||
#include "Machines/ShamirMachine.h"
|
||||
|
||||
template<class T>
|
||||
class ShamirMC : public MAC_Check_Base<T>
|
||||
|
||||
@@ -14,7 +14,12 @@ void AuthValue::assign(const word& value, const int128& mac_key, bool not_first_
|
||||
share = 0;
|
||||
else
|
||||
share = value;
|
||||
#ifdef __PCLMUL__
|
||||
mac = _mm_clmulepi64_si128(_mm_cvtsi64_si128(mac_key.get_lower()), _mm_cvtsi64_si128(value), 0);
|
||||
#else
|
||||
(void) mac_key;
|
||||
throw runtime_error("need to compile with PCLMUL support");
|
||||
#endif
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream& o, const AuthValue& auth_value)
|
||||
|
||||
11
BMR/Key.h
11
BMR/Key.h
@@ -12,6 +12,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "Tools/FlexBuffer.h"
|
||||
#include "Math/gf2nlong.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -54,8 +55,7 @@ ostream& operator<<(ostream& o, const __m128i& x);
|
||||
|
||||
|
||||
inline bool Key::operator==(const Key& other) {
|
||||
__m128i neq = _mm_xor_si128(r, other.r);
|
||||
return _mm_test_all_zeros(neq,neq);
|
||||
return int128(r) == other.r;
|
||||
}
|
||||
|
||||
inline Key& Key::operator-=(const Key& other) {
|
||||
@@ -88,7 +88,14 @@ inline void Key::set_signal(bool signal)
|
||||
|
||||
inline Key Key::doubling(int i) const
|
||||
{
|
||||
#ifdef __AVX2__
|
||||
return _mm_sllv_epi64(r, _mm_set_epi64x(i, i));
|
||||
#else
|
||||
uint64_t halfs[2];
|
||||
halfs[1] = _mm_cvtsi128_si64(_mm_unpackhi_epi64(r, r)) << i;
|
||||
halfs[0] = _mm_cvtsi128_si64(r) << i;
|
||||
return _mm_loadu_si128((__m128i*)halfs);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <mutex>
|
||||
#include <boost/atomic.hpp>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include "Register.h"
|
||||
#include "GarbledGate.h"
|
||||
@@ -31,7 +31,7 @@ class BooleanCircuit;
|
||||
#ifndef N_EVAL_THREADS
|
||||
// Default Intel desktop processor has 8 half cores.
|
||||
// This is beneficial if only one AES available per full core.
|
||||
#define N_EVAL_THREADS (get_nprocs())
|
||||
#define N_EVAL_THREADS (thread::hardware_concurrency())
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "GC/Instruction.hpp"
|
||||
#include "GC/Program.hpp"
|
||||
|
||||
#include "Processor/Instruction.hpp"
|
||||
|
||||
namespace GC
|
||||
{
|
||||
|
||||
|
||||
200
BMR/aes.cpp
200
BMR/aes.cpp
@@ -1,4 +1,5 @@
|
||||
#include "aes.h"
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "StdAfx.h"
|
||||
@@ -10,6 +11,7 @@ void AES_128_Key_Expansion(const unsigned char *userkey, AES_KEY *aesKey)
|
||||
//block *kp = (block *)&aesKey;
|
||||
aesKey->rd_key[0] = x0 = _mm_loadu_si128((block*)userkey);
|
||||
x2 = _mm_setzero_si128();
|
||||
#ifdef __AES__
|
||||
EXPAND_ASSIST(x0, x1, x2, x0, 255, 1); aesKey->rd_key[1] = x0;
|
||||
EXPAND_ASSIST(x0, x1, x2, x0, 255, 2); aesKey->rd_key[2] = x0;
|
||||
EXPAND_ASSIST(x0, x1, x2, x0, 255, 4); aesKey->rd_key[3] = x0;
|
||||
@@ -20,198 +22,8 @@ void AES_128_Key_Expansion(const unsigned char *userkey, AES_KEY *aesKey)
|
||||
EXPAND_ASSIST(x0, x1, x2, x0, 255, 128); aesKey->rd_key[8] = x0;
|
||||
EXPAND_ASSIST(x0, x1, x2, x0, 255, 27); aesKey->rd_key[9] = x0;
|
||||
EXPAND_ASSIST(x0, x1, x2, x0, 255, 54); aesKey->rd_key[10] = x0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AES_192_Key_Expansion(const unsigned char *userkey, AES_KEY *aesKey)
|
||||
{
|
||||
__m128i x0,x1,x2,x3,tmp,*kp = (block *)&aesKey;
|
||||
kp[0] = x0 = _mm_loadu_si128((block*)userkey);
|
||||
tmp = x3 = _mm_loadu_si128((block*)(userkey+16));
|
||||
x2 = _mm_setzero_si128();
|
||||
EXPAND192_STEP(1,1);
|
||||
EXPAND192_STEP(4,4);
|
||||
EXPAND192_STEP(7,16);
|
||||
EXPAND192_STEP(10,64);
|
||||
}
|
||||
|
||||
void AES_256_Key_Expansion(const unsigned char *userkey, AES_KEY *aesKey)
|
||||
{
|
||||
__m128i x0, x1, x2, x3;/* , *kp = (block *)&aesKey;*/
|
||||
aesKey->rd_key[0] = x0 = _mm_loadu_si128((block*)userkey);
|
||||
aesKey->rd_key[1] = x3 = _mm_loadu_si128((block*)(userkey + 16));
|
||||
x2 = _mm_setzero_si128();
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 1); aesKey->rd_key[2] = x0;
|
||||
EXPAND_ASSIST(x3, x1, x2, x0, 170, 1); aesKey->rd_key[3] = x3;
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 2); aesKey->rd_key[4] = x0;
|
||||
EXPAND_ASSIST(x3, x1, x2, x0, 170, 2); aesKey->rd_key[5] = x3;
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 4); aesKey->rd_key[6] = x0;
|
||||
EXPAND_ASSIST(x3, x1, x2, x0, 170, 4); aesKey->rd_key[7] = x3;
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 8); aesKey->rd_key[8] = x0;
|
||||
EXPAND_ASSIST(x3, x1, x2, x0, 170, 8); aesKey->rd_key[9] = x3;
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 16); aesKey->rd_key[10] = x0;
|
||||
EXPAND_ASSIST(x3, x1, x2, x0, 170, 16); aesKey->rd_key[11] = x3;
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 32); aesKey->rd_key[12] = x0;
|
||||
EXPAND_ASSIST(x3, x1, x2, x0, 170, 32); aesKey->rd_key[13] = x3;
|
||||
EXPAND_ASSIST(x0, x1, x2, x3, 255, 64); aesKey->rd_key[14] = x0;
|
||||
}
|
||||
|
||||
void AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *aesKey)
|
||||
{
|
||||
if (bits == 128) {
|
||||
AES_128_Key_Expansion(userKey, aesKey);
|
||||
} else if (bits == 192) {
|
||||
AES_192_Key_Expansion(userKey, aesKey);
|
||||
} else if (bits == 256) {
|
||||
AES_256_Key_Expansion(userKey, aesKey);
|
||||
}
|
||||
|
||||
aesKey->rounds = 6 + bits / 32;
|
||||
|
||||
}
|
||||
|
||||
void AES_encryptC(block *in, block *out, AES_KEY *aesKey)
|
||||
{
|
||||
int j, rnds = ROUNDS(aesKey);
|
||||
const __m128i *sched = ((__m128i *)(aesKey->rd_key));
|
||||
__m128i tmp = _mm_load_si128((__m128i*)in);
|
||||
tmp = _mm_xor_si128(tmp, sched[0]);
|
||||
for (j = 1; j<rnds; j++) tmp = _mm_aesenc_si128(tmp, sched[j]);
|
||||
tmp = _mm_aesenclast_si128(tmp, sched[j]);
|
||||
_mm_store_si128((__m128i*)out, tmp);
|
||||
}
|
||||
|
||||
|
||||
void AES_ecb_encrypt(block *blk, AES_KEY *aesKey) {
|
||||
unsigned j, rnds = ROUNDS(aesKey);
|
||||
const block *sched = ((block *)(aesKey->rd_key));
|
||||
|
||||
*blk = _mm_xor_si128(*blk, sched[0]);
|
||||
for (j = 1; j<rnds; ++j)
|
||||
*blk = _mm_aesenc_si128(*blk, sched[j]);
|
||||
*blk = _mm_aesenclast_si128(*blk, sched[j]);
|
||||
}
|
||||
|
||||
void AES_ecb_encrypt_blks(block *blks, unsigned nblks, AES_KEY *aesKey) {
|
||||
unsigned i,j,rnds=ROUNDS(aesKey);
|
||||
const block *sched = ((block *)(aesKey->rd_key));
|
||||
for (i=0; i<nblks; ++i)
|
||||
blks[i] =_mm_xor_si128(blks[i], sched[0]);
|
||||
for(j=1; j<rnds; ++j)
|
||||
for (i=0; i<nblks; ++i)
|
||||
blks[i] = _mm_aesenc_si128(blks[i], sched[j]);
|
||||
for (i=0; i<nblks; ++i)
|
||||
blks[i] =_mm_aesenclast_si128(blks[i], sched[j]);
|
||||
}
|
||||
|
||||
void AES_ecb_encrypt_blks_4(block *blks, AES_KEY *aesKey) {
|
||||
unsigned j, rnds = ROUNDS(aesKey);
|
||||
const block *sched = ((block *)(aesKey->rd_key));
|
||||
blks[0] = _mm_xor_si128(blks[0], sched[0]);
|
||||
blks[1] = _mm_xor_si128(blks[1], sched[0]);
|
||||
blks[2] = _mm_xor_si128(blks[2], sched[0]);
|
||||
blks[3] = _mm_xor_si128(blks[3], sched[0]);
|
||||
|
||||
for (j = 1; j < rnds; ++j){
|
||||
blks[0] = _mm_aesenc_si128(blks[0], sched[j]);
|
||||
blks[1] = _mm_aesenc_si128(blks[1], sched[j]);
|
||||
blks[2] = _mm_aesenc_si128(blks[2], sched[j]);
|
||||
blks[3] = _mm_aesenc_si128(blks[3], sched[j]);
|
||||
}
|
||||
blks[0] = _mm_aesenclast_si128(blks[0], sched[j]);
|
||||
blks[1] = _mm_aesenclast_si128(blks[1], sched[j]);
|
||||
blks[2] = _mm_aesenclast_si128(blks[2], sched[j]);
|
||||
blks[3] = _mm_aesenclast_si128(blks[3], sched[j]);
|
||||
}
|
||||
|
||||
|
||||
void AES_ecb_encrypt_blks_2_in_out(block *in, block *out, AES_KEY *aesKey) {
|
||||
|
||||
unsigned j, rnds = ROUNDS(aesKey);
|
||||
const block *sched = ((block *)(aesKey->rd_key));
|
||||
|
||||
out[0] = _mm_xor_si128(in[0], sched[0]);
|
||||
out[1] = _mm_xor_si128(in[1], sched[0]);
|
||||
|
||||
for (j = 1; j < rnds; ++j){
|
||||
out[0] = _mm_aesenc_si128(out[0], sched[j]);
|
||||
out[1] = _mm_aesenc_si128(out[1], sched[j]);
|
||||
|
||||
}
|
||||
out[0] = _mm_aesenclast_si128(out[0], sched[j]);
|
||||
out[1] = _mm_aesenclast_si128(out[1], sched[j]);
|
||||
}
|
||||
|
||||
void AES_ecb_encrypt_blks_4_in_out(block *in, block *out, AES_KEY *aesKey) {
|
||||
unsigned j, rnds = ROUNDS(aesKey);
|
||||
const block *sched = ((block *)(aesKey->rd_key));
|
||||
//block temp[4];
|
||||
|
||||
out[0] = _mm_xor_si128(in[0], sched[0]);
|
||||
out[1] = _mm_xor_si128(in[1], sched[0]);
|
||||
out[2] = _mm_xor_si128(in[2], sched[0]);
|
||||
out[3] = _mm_xor_si128(in[3], sched[0]);
|
||||
|
||||
for (j = 1; j < rnds; ++j){
|
||||
out[0] = _mm_aesenc_si128(out[0], sched[j]);
|
||||
out[1] = _mm_aesenc_si128(out[1], sched[j]);
|
||||
out[2] = _mm_aesenc_si128(out[2], sched[j]);
|
||||
out[3] = _mm_aesenc_si128(out[3], sched[j]);
|
||||
}
|
||||
out[0] = _mm_aesenclast_si128(out[0], sched[j]);
|
||||
out[1] = _mm_aesenclast_si128(out[1], sched[j]);
|
||||
out[2] = _mm_aesenclast_si128(out[2], sched[j]);
|
||||
out[3] = _mm_aesenclast_si128(out[3], sched[j]);
|
||||
}
|
||||
|
||||
void AES_ecb_encrypt_chunk_in_out(block *in, block *out, unsigned nblks, AES_KEY *aesKey) {
|
||||
|
||||
int numberOfLoops = nblks / 8;
|
||||
int blocksPipeLined = numberOfLoops * 8;
|
||||
int remainingEncrypts = nblks - blocksPipeLined;
|
||||
|
||||
unsigned j, rnds = ROUNDS(aesKey);
|
||||
const block *sched = ((block *)(aesKey->rd_key));
|
||||
|
||||
for (int i = 0; i < numberOfLoops; i++){
|
||||
|
||||
out[0 + i * 8] = _mm_xor_si128(in[0 + i * 8], sched[0]);
|
||||
out[1 + i * 8] = _mm_xor_si128(in[1 + i * 8], sched[0]);
|
||||
out[2 + i * 8] = _mm_xor_si128(in[2 + i * 8], sched[0]);
|
||||
out[3 + i * 8] = _mm_xor_si128(in[3 + i * 8], sched[0]);
|
||||
out[4 + i * 8] = _mm_xor_si128(in[4 + i * 8], sched[0]);
|
||||
out[5 + i * 8] = _mm_xor_si128(in[5 + i * 8], sched[0]);
|
||||
out[6 + i * 8] = _mm_xor_si128(in[6 + i * 8], sched[0]);
|
||||
out[7 + i * 8] = _mm_xor_si128(in[7 + i * 8], sched[0]);
|
||||
|
||||
for (j = 1; j < rnds; ++j){
|
||||
out[0 + i * 8] = _mm_aesenc_si128(out[0 + i * 8], sched[j]);
|
||||
out[1 + i * 8] = _mm_aesenc_si128(out[1 + i * 8], sched[j]);
|
||||
out[2 + i * 8] = _mm_aesenc_si128(out[2 + i * 8], sched[j]);
|
||||
out[3 + i * 8] = _mm_aesenc_si128(out[3 + i * 8], sched[j]);
|
||||
out[4 + i * 8] = _mm_aesenc_si128(out[4 + i * 8], sched[j]);
|
||||
out[5 + i * 8] = _mm_aesenc_si128(out[5 + i * 8], sched[j]);
|
||||
out[6 + i * 8] = _mm_aesenc_si128(out[6 + i * 8], sched[j]);
|
||||
out[7 + i * 8] = _mm_aesenc_si128(out[7 + i * 8], sched[j]);
|
||||
}
|
||||
out[0 + i * 8] = _mm_aesenclast_si128(out[0 + i * 8], sched[j]);
|
||||
out[1 + i * 8] = _mm_aesenclast_si128(out[1 + i * 8], sched[j]);
|
||||
out[2 + i * 8] = _mm_aesenclast_si128(out[2 + i * 8], sched[j]);
|
||||
out[3 + i * 8] = _mm_aesenclast_si128(out[3 + i * 8], sched[j]);
|
||||
out[4 + i * 8] = _mm_aesenclast_si128(out[4 + i * 8], sched[j]);
|
||||
out[5 + i * 8] = _mm_aesenclast_si128(out[5 + i * 8], sched[j]);
|
||||
out[6 + i * 8] = _mm_aesenclast_si128(out[6 + i * 8], sched[j]);
|
||||
out[7 + i * 8] = _mm_aesenclast_si128(out[7 + i * 8], sched[j]);
|
||||
}
|
||||
|
||||
for (int i = blocksPipeLined; i < blocksPipeLined + remainingEncrypts; ++i){
|
||||
out[i] = _mm_xor_si128(in[i], sched[0]);
|
||||
for (j = 1; j < rnds; ++j)
|
||||
{
|
||||
out[i] = _mm_aesenc_si128(out[i], sched[j]);
|
||||
}
|
||||
out[i] = _mm_aesenclast_si128(out[i], sched[j]);
|
||||
}
|
||||
|
||||
#else
|
||||
(void) x1, (void) x2;
|
||||
throw std::runtime_error("need to compile with AES-NI support");
|
||||
#endif
|
||||
}
|
||||
|
||||
31
BMR/aes.h
31
BMR/aes.h
@@ -24,7 +24,6 @@
|
||||
|
||||
|
||||
typedef struct { block rd_key[15]; int rounds; } AES_KEY;
|
||||
#define ROUNDS(ctx) ((ctx)->rounds)
|
||||
|
||||
#define EXPAND_ASSIST(v1,v2,v3,v4,shuff_const,aes_const) \
|
||||
v2 = _mm_aeskeygenassist_si128(v4,aes_const); \
|
||||
@@ -37,36 +36,6 @@ typedef struct { block rd_key[15]; int rounds; } AES_KEY;
|
||||
v2 = _mm_shuffle_epi32(v2,shuff_const); \
|
||||
v1 = _mm_xor_si128(v1,v2)
|
||||
|
||||
#define EXPAND192_STEP(idx,aes_const) \
|
||||
EXPAND_ASSIST(x0,x1,x2,x3,85,aes_const); \
|
||||
x3 = _mm_xor_si128(x3,_mm_slli_si128 (x3, 4)); \
|
||||
x3 = _mm_xor_si128(x3,_mm_shuffle_epi32(x0, 255)); \
|
||||
kp[idx] = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(tmp), \
|
||||
_mm_castsi128_ps(x0), 68)); \
|
||||
kp[idx+1] = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(x0), \
|
||||
_mm_castsi128_ps(x3), 78)); \
|
||||
EXPAND_ASSIST(x0,x1,x2,x3,85,(aes_const*2)); \
|
||||
x3 = _mm_xor_si128(x3,_mm_slli_si128 (x3, 4)); \
|
||||
x3 = _mm_xor_si128(x3,_mm_shuffle_epi32(x0, 255)); \
|
||||
kp[idx+2] = x0; tmp = x3
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void AES_128_Key_Expansion(const unsigned char *userkey, AES_KEY* aesKey);
|
||||
void AES_192_Key_Expansion(const unsigned char *userkey, AES_KEY* aesKey);
|
||||
void AES_256_Key_Expansion(const unsigned char *userkey, AES_KEY* aesKey);
|
||||
void AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *aesKey);
|
||||
|
||||
void AES_encryptC(block *in, block *out, AES_KEY *aesKey);
|
||||
void AES_ecb_encrypt(block *blk, AES_KEY *aesKey);
|
||||
|
||||
void AES_ecb_encrypt_blks(block *blks, unsigned nblks, AES_KEY *aesKey);
|
||||
void AES_ecb_encrypt_blks_4(block *blk, AES_KEY *aesKey);
|
||||
void AES_ecb_encrypt_blks_4_in_out(block *in, block *out, AES_KEY *aesKey);
|
||||
void AES_ecb_encrypt_blks_2_in_out(block *in, block *out, AES_KEY *aesKey);
|
||||
void AES_ecb_encrypt_chunk_in_out(block *in, block *out, unsigned nblks, AES_KEY *aesKey);
|
||||
|
||||
|
||||
#endif /* PROTOCOL_INC_AES_H_ */
|
||||
|
||||
@@ -36,7 +36,7 @@ Server::Server(int port, int expected_clients, ServerUpdatable* updatable, unsig
|
||||
_servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
_servaddr.sin_port = htons(_port);
|
||||
|
||||
if( 0 != bind(_servfd, (struct sockaddr *) &_servaddr, sizeof(_servaddr)) )
|
||||
if( 0 != ::bind(_servfd, (struct sockaddr *) &_servaddr, sizeof(_servaddr)) )
|
||||
printf("Server:: Error binding to %d: \n%s\n", _port, strerror(errno));
|
||||
|
||||
if(0 != listen(_servfd, _expected_clients))
|
||||
|
||||
21
BMR/prf.cpp
21
BMR/prf.cpp
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* prf.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "prf.h"
|
||||
#include "aes.h"
|
||||
#include "proto_utils.h"
|
||||
|
||||
void PRF_single(const Key& key, char* input, char* output)
|
||||
{
|
||||
// printf("prf_single\n");
|
||||
// std::cout << *key;
|
||||
// phex(input, 16);
|
||||
AES_KEY aes_key;
|
||||
AES_128_Key_Expansion((const unsigned char*)(&(key.r)), &aes_key);
|
||||
aes_key.rounds=10;
|
||||
AES_encryptC((block*)input, (block*)output, &aes_key);
|
||||
// phex(output, 16);
|
||||
}
|
||||
@@ -11,15 +11,6 @@
|
||||
|
||||
#include "Tools/aes.h"
|
||||
|
||||
void PRF_single(const Key& key, char* input, char* output);
|
||||
|
||||
inline Key PRF_single(const Key& key, const Key& input)
|
||||
{
|
||||
Key output;
|
||||
PRF_single(key, (char*)&input, (char*)&output);
|
||||
return output;
|
||||
}
|
||||
|
||||
inline void PRF_chunk(const Key& key, char* input, char* output, int number)
|
||||
{
|
||||
__m128i* in = (__m128i*)input;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
The changelog explains changes pulled through from the private development repository. Bug fixes and small enchancements are committed between releases and not documented here.
|
||||
|
||||
## 0.0.7 (Feb 14, 2019)
|
||||
|
||||
- Simplified installation on macOS
|
||||
- Optimized matrix multiplication
|
||||
- Data type for quantization
|
||||
|
||||
## 0.0.6 (Jan 5, 2019)
|
||||
|
||||
- Shamir secret sharing
|
||||
|
||||
18
CONFIG
18
CONFIG
@@ -4,6 +4,7 @@ OPTIM= -O3
|
||||
#PROF = -pg
|
||||
#DEBUG = -DDEBUG
|
||||
#MEMPROTECT = -DMEMPROTECT
|
||||
GDEBUG = -g
|
||||
|
||||
# set this to your preferred local storage directory
|
||||
PREP_DIR = '-DPREP_DIR="Player-Data/"'
|
||||
@@ -16,8 +17,15 @@ USE_NTL = 0
|
||||
USE_GF2N_LONG = 1
|
||||
|
||||
# set to -march=<architecture> for optimization
|
||||
# AVX2 support (Haswell or later) changes the bit matrix transpose
|
||||
ARCH = -mtune=native -mavx
|
||||
# AES-NI is required for BMR
|
||||
# PCLMUL is required for GF(2^128) computation
|
||||
# AVX2 support (Haswell or later) is used to optimize OT
|
||||
# AVX/AVX2 is required for replicated binary secret sharing
|
||||
# BMI2 is used to optimize multiplication modulo a prime
|
||||
ARCH = -mtune=native -msse4.1 -maes -mpclmul -mavx -mavx2 -mbmi2
|
||||
|
||||
# allow to set compiler in CONFIG.mine
|
||||
CXX = g++
|
||||
|
||||
#use CONFIG.mine to overwrite DIR settings
|
||||
-include CONFIG.mine
|
||||
@@ -30,7 +38,7 @@ endif
|
||||
# Default is 2, which suffices for 128-bit p
|
||||
# MOD = -DMAX_MOD_SZ=2
|
||||
|
||||
LDLIBS = -lmpirxx -lmpir -lsodium $(MY_LDLIBS) -lm -lpthread
|
||||
LDLIBS = -lmpirxx -lmpir -lsodium $(MY_LDLIBS)
|
||||
LDLIBS += -lboost_system -lssl -lcrypto
|
||||
|
||||
ifeq ($(USE_NTL),1)
|
||||
@@ -44,8 +52,6 @@ endif
|
||||
|
||||
BOOST = -lboost_system -lboost_thread $(MY_BOOST)
|
||||
|
||||
CXX = g++ -no-pie
|
||||
#CXX = clang++
|
||||
CFLAGS += $(ARCH) $(MY_CFLAGS) -g -Wextra -Wall $(OPTIM) -I$(ROOT) -pthread $(PROF) $(DEBUG) $(MOD) $(MEMPROTECT) $(GF2N_LONG) $(PREP_DIR) -maes -mpclmul -msse4.1 -mavx -mavx2 -mbmi2 --std=c++11 -Werror
|
||||
CFLAGS += $(ARCH) $(MY_CFLAGS) $(GDEBUG) -Wextra -Wall $(OPTIM) -I$(ROOT) -pthread $(PROF) $(DEBUG) $(MOD) $(MEMPROTECT) $(GF2N_LONG) $(PREP_DIR) -std=c++11 -Werror
|
||||
CPPFLAGS = $(CFLAGS)
|
||||
LD = $(CXX)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "Processor/Data_Files.h"
|
||||
|
||||
#include "Auth/fake-stuff.hpp"
|
||||
#include "Processor/Data_Files.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
@@ -6,11 +6,10 @@ from Compiler import util, oram, floatingpoint
|
||||
import Compiler.GC.instructions as inst
|
||||
import operator
|
||||
|
||||
class bits(Tape.Register):
|
||||
class bits(Tape.Register, _structure):
|
||||
n = 40
|
||||
size = 1
|
||||
PreOp = staticmethod(floatingpoint.PreOpN)
|
||||
MemValue = staticmethod(lambda value: MemValue(value))
|
||||
decomposed = None
|
||||
@staticmethod
|
||||
def PreOR(l):
|
||||
@@ -72,7 +71,10 @@ class bits(Tape.Register):
|
||||
def n_elements():
|
||||
return 1
|
||||
@classmethod
|
||||
def load_mem(cls, address, mem_type=None):
|
||||
def load_mem(cls, address, mem_type=None, size=None):
|
||||
if size not in (None, 1):
|
||||
v = [cls.load_mem(address + i) for i in range(size)]
|
||||
return cls.vec(v)
|
||||
res = cls()
|
||||
if mem_type == 'sd':
|
||||
return cls.load_dynamic_mem(address)
|
||||
@@ -376,6 +378,9 @@ class sbits(bits):
|
||||
|
||||
class sbitvec(object):
|
||||
@classmethod
|
||||
def get_type(cls, n):
|
||||
return cls
|
||||
@classmethod
|
||||
def from_vec(cls, vector):
|
||||
res = cls()
|
||||
res.v = list(vector)
|
||||
@@ -419,6 +424,15 @@ class sbitvec(object):
|
||||
@classmethod
|
||||
def conv(cls, other):
|
||||
return cls.from_vec(other.v)
|
||||
@property
|
||||
def size(self):
|
||||
return self.v[0].n
|
||||
def store_in_mem(self, address):
|
||||
for i, x in enumerate(self.elements()):
|
||||
x.store_in_mem(address + i)
|
||||
def bit_decompose(self):
|
||||
return self.v
|
||||
bit_compose = from_vec
|
||||
|
||||
class bit(object):
|
||||
n = 1
|
||||
@@ -499,7 +513,9 @@ class sbitint(_bitint, _number, sbits):
|
||||
bin_type = None
|
||||
types = {}
|
||||
@classmethod
|
||||
def get_type(cls, n):
|
||||
def get_type(cls, n, other=None):
|
||||
if isinstance(other, sbitvec):
|
||||
return sbitvec
|
||||
if n in cls.types:
|
||||
return cls.types[n]
|
||||
sbits_type = sbits.get_type(n)
|
||||
@@ -511,6 +527,12 @@ class sbitint(_bitint, _number, sbits):
|
||||
cls.types[n] = _
|
||||
return _
|
||||
@classmethod
|
||||
def combo_type(cls, other):
|
||||
if isinstance(other, sbitintvec):
|
||||
return sbitintvec
|
||||
else:
|
||||
return cls
|
||||
@classmethod
|
||||
def new(cls, value=None, n=None):
|
||||
return cls.get_type(n)(value)
|
||||
def set_length(*args):
|
||||
@@ -523,7 +545,9 @@ class sbitint(_bitint, _number, sbits):
|
||||
return super(sbitint, cls).bit_compose(bits)
|
||||
def force_bit_decompose(self, n_bits=None):
|
||||
return sbits.bit_decompose(self, n_bits)
|
||||
def TruncMul(self, other, k, m, kappa=None):
|
||||
def TruncMul(self, other, k, m, kappa=None, nearest=False):
|
||||
if nearest:
|
||||
raise CompilerError('round to nearest not implemented')
|
||||
self_bits = self.bit_decompose()
|
||||
other_bits = other.bit_decompose()
|
||||
if len(self_bits) + len(other_bits) != k:
|
||||
@@ -532,10 +556,12 @@ class sbitint(_bitint, _number, sbits):
|
||||
(len(self_bits), len(other_bits), k))
|
||||
t = self.get_type(k)
|
||||
a = t.bit_compose(self_bits + [self_bits[-1]] * (k - len(self_bits)))
|
||||
t = other.get_type(k)
|
||||
b = t.bit_compose(other_bits + [other_bits[-1]] * (k - len(other_bits)))
|
||||
product = a * b
|
||||
res_bits = product.bit_decompose()[m:k]
|
||||
return self.bit_compose(res_bits)
|
||||
t = self.combo_type(other)
|
||||
return t.bit_compose(res_bits)
|
||||
def Norm(self, k, f, kappa=None, simplex_flag=False):
|
||||
absolute_val = abs(self)
|
||||
#next 2 lines actually compute the SufOR for little indian encoding
|
||||
@@ -557,17 +583,32 @@ class sbitint(_bitint, _number, sbits):
|
||||
bits = self.bit_decompose()
|
||||
bits += [bits[-1]] * (n - len(bits))
|
||||
return self.get_type(n).bit_compose(bits)
|
||||
def __mul__(self, other):
|
||||
if isinstance(other, sbitintvec):
|
||||
return other * self
|
||||
else:
|
||||
return super(sbitint, self).__mul__(other)
|
||||
|
||||
class sbitintvec(sbitvec):
|
||||
def __add__(self, other):
|
||||
if other is 0:
|
||||
return self
|
||||
assert(len(self.v) == len(other.v))
|
||||
return self.from_vec(sbitint.bit_adder(self.v, other.v))
|
||||
v = sbitint.bit_adder(self.v, other.v)
|
||||
return self.from_vec(v)
|
||||
__radd__ = __add__
|
||||
def less_than(self, other, *args, **kwargs):
|
||||
assert(len(self.v) == len(other.v))
|
||||
return self.from_vec(sbitint.bit_less_than(self.v, other.v))
|
||||
def __mul__(self, other):
|
||||
assert isinstance(other, sbitint)
|
||||
matrix = [[x * b for x in self.v] for b in other.bit_decompose()]
|
||||
v = sbitint.wallace_tree_from_matrix(matrix)
|
||||
return self.from_vec(v)
|
||||
__rmul__ = __mul__
|
||||
reduce_after_mul = lambda x: x
|
||||
|
||||
sbitint.vec = sbitintvec
|
||||
|
||||
class cbitfix(object):
|
||||
def __init__(self, value):
|
||||
@@ -585,6 +626,13 @@ class sbitfix(_fix):
|
||||
def set_precision(cls, f, k=None):
|
||||
super(cls, sbitfix).set_precision(f, k)
|
||||
cls.int_type = sbitint.get_type(cls.k)
|
||||
@classmethod
|
||||
def load_mem(cls, address, size=None):
|
||||
if size not in (None, 1):
|
||||
v = [cls.int_type.load_mem(address + i) for i in range(size)]
|
||||
return sbitfixvec._new(sbitintvec(v))
|
||||
else:
|
||||
return super(sbitfix, cls).load_mem(address)
|
||||
def __xor__(self, other):
|
||||
return type(self)(self.v ^ other.v)
|
||||
def __mul__(self, other):
|
||||
@@ -596,3 +644,17 @@ class sbitfix(_fix):
|
||||
__rmul__ = __mul__
|
||||
|
||||
sbitfix.set_precision(20, 41)
|
||||
|
||||
class sbitfixvec(_fix):
|
||||
int_type = sbitintvec
|
||||
float_type = type(None)
|
||||
@staticmethod
|
||||
@property
|
||||
def f():
|
||||
return sbitfix.f
|
||||
@staticmethod
|
||||
@property
|
||||
def k():
|
||||
return sbitfix.k
|
||||
|
||||
sbitfix.vec = sbitfixvec
|
||||
|
||||
@@ -43,8 +43,7 @@ class StraightlineAllocator:
|
||||
if base.vector:
|
||||
for i,r in enumerate(base.vector):
|
||||
r.i = self.alloc[base] + i
|
||||
else:
|
||||
base.i = self.alloc[base]
|
||||
base.i = self.alloc[base]
|
||||
|
||||
def dealloc_reg(self, reg, inst, free):
|
||||
self.dealloc.add(reg)
|
||||
@@ -57,6 +56,7 @@ class StraightlineAllocator:
|
||||
return
|
||||
free[reg.reg_type, base.size].add(self.alloc[base])
|
||||
if inst.is_vec() and base.vector:
|
||||
self.defined[base] = inst
|
||||
for i in base.vector:
|
||||
self.defined[i] = inst
|
||||
else:
|
||||
|
||||
@@ -108,67 +108,54 @@ def Trunc(d, a, k, m, kappa, signed):
|
||||
def TruncRing(d, a, k, m, signed):
|
||||
a_prime = Mod2mRing(None, a, k, m, signed)
|
||||
a -= a_prime
|
||||
res = TruncZeroesInRing(a, k, m, signed)
|
||||
res = TruncLeakyInRing(a, k, m, signed)
|
||||
if d is not None:
|
||||
movs(d, res)
|
||||
return res
|
||||
|
||||
def TruncZeroesInRing(a, k, m, signed):
|
||||
def TruncZeroes(a, k, m, signed):
|
||||
if program.options.ring:
|
||||
return TruncLeakyInRing(a, k, m, signed)
|
||||
else:
|
||||
import types
|
||||
tmp = types.cint()
|
||||
inv2m(tmp, m)
|
||||
return a * tmp
|
||||
|
||||
def TruncLeakyInRing(a, k, m, signed):
|
||||
"""
|
||||
Returns a >> m.
|
||||
Requires 2^m | a and a < 2^k.
|
||||
Requires a < 2^k and leaks a % 2^m (needs to be constant or random).
|
||||
"""
|
||||
assert k > m
|
||||
assert int(program.options.ring) >= k
|
||||
from types import sint, intbitint, cint, cgf2n
|
||||
n_bits = k - m
|
||||
n_shift = int(program.options.ring) - n_bits
|
||||
r_bits = [sint.get_random_bit() for i in range(n_bits)]
|
||||
r = sint.bit_compose(r_bits)
|
||||
shifted = ((a << (n_shift - m)) - (r << n_shift)).reveal()
|
||||
masked = shifted >> n_shift
|
||||
res_bits = intbitint.bit_adder(r_bits, masked.bit_decompose(n_bits))
|
||||
res = sint.bit_compose(res_bits)
|
||||
if signed:
|
||||
res = sint.conv(res_bits[-1].if_else(res - (sint(1) << n_bits),
|
||||
res))
|
||||
a += (1 << (k - 1))
|
||||
shifted = ((a << (n_shift - m)) + (r << n_shift)).reveal()
|
||||
masked = shifted >> n_shift
|
||||
u = sint()
|
||||
BitLTL(u, masked, r_bits, 0)
|
||||
res = (u << n_bits) + masked - r
|
||||
if signed:
|
||||
res -= (1 << (n_bits - 1))
|
||||
return res
|
||||
|
||||
def TruncRoundNearest(a, k, m, kappa):
|
||||
def TruncRoundNearest(a, k, m, kappa, signed=False):
|
||||
"""
|
||||
Returns a / 2^m, rounded to the nearest integer.
|
||||
|
||||
k: bit length of m
|
||||
k: bit length of a
|
||||
m: compile-time integer
|
||||
"""
|
||||
from types import sint, cint
|
||||
from library import reveal, load_int_to_secret
|
||||
if m == 1:
|
||||
if program.options.ring:
|
||||
lsb = Mod2mRing(None, a, k, 1, False)
|
||||
return TruncRing(None, a + lsb, k + 1, 1, False)
|
||||
else:
|
||||
lsb = sint()
|
||||
Mod2(lsb, a, k, kappa, False)
|
||||
return (a + lsb) / 2
|
||||
r_dprime = sint()
|
||||
r_prime = sint()
|
||||
r = [sint() for i in range(m)]
|
||||
u = sint()
|
||||
PRandM(r_dprime, r_prime, r, k, m, kappa)
|
||||
c = reveal((cint(1) << (k - 1)) + a + (cint(1) << m) * r_dprime + r_prime)
|
||||
c_prime = c % (cint(1) << (m - 1))
|
||||
if const_rounds:
|
||||
BitLTC1(u, c_prime, r[:-1], kappa)
|
||||
else:
|
||||
BitLTL(u, c_prime, r[:-1], kappa)
|
||||
bit = ((c - c_prime) >> (m - 1)) % 2
|
||||
xor = bit + u - 2 * bit * u
|
||||
prod = xor * r[-1]
|
||||
# u_prime = xor * u + (1 - xor) * r[-1]
|
||||
u_prime = bit * u + u - 2 * bit * u + r[-1] - prod
|
||||
a_prime = (c % (cint(1) << m)) - r_prime + (cint(1) << m) * u_prime
|
||||
d = (a - a_prime) >> m
|
||||
rounding = xor + r[-1] - 2 * prod
|
||||
return d + rounding
|
||||
from types import sint
|
||||
res = sint()
|
||||
Trunc(res, a + (1 << (m - 1)), k + 1, m, kappa, signed)
|
||||
return res
|
||||
|
||||
def Mod2m(a_prime, a, k, m, kappa, signed):
|
||||
"""
|
||||
|
||||
@@ -369,6 +369,8 @@ def Trunc(a, l, m, kappa, compute_modulo=False):
|
||||
x, pow2m = B2U(m, l, kappa)
|
||||
#assert(pow2m.value == 2**m.value)
|
||||
#assert(sum(b.value for b in x) == m.value)
|
||||
if program.Program.prog.options.ring and not compute_modulo:
|
||||
return TruncInRing(a, l, pow2m)
|
||||
for i in range(l):
|
||||
bit(r[i])
|
||||
t1 = two_power(i) * r[i]
|
||||
@@ -418,7 +420,7 @@ def TruncRoundNearestAdjustOverflow(a, length, target_length, kappa):
|
||||
overflow = t.greater_equal(two_power(target_length), target_length + 1, kappa)
|
||||
if program.Program.prog.options.ring:
|
||||
s = (1 - overflow) * t + \
|
||||
comparison.TruncZeroesInRing(overflow * t, length, 1, False)
|
||||
comparison.TruncLeakyInRing(overflow * t, length, 1, False)
|
||||
else:
|
||||
s = (1 - overflow) * t + overflow * t / 2
|
||||
return s, overflow
|
||||
@@ -484,9 +486,22 @@ def TruncPr(a, k, m, kappa=None):
|
||||
def TruncPrRing(a, k, m):
|
||||
if m == 0:
|
||||
return a
|
||||
res = types.sint()
|
||||
comparison.TruncRing(res, a, k, m, True)
|
||||
return res
|
||||
n_ring = int(program.Program.prog.options.ring)
|
||||
if k == n_ring:
|
||||
for i in range(m):
|
||||
a += types.sint.get_random_bit() << i
|
||||
return comparison.TruncLeakyInRing(a, k, m, True)
|
||||
else:
|
||||
from types import sint
|
||||
# extra bit to mask overflow
|
||||
r_bits = [sint.get_random_bit() for i in range(k + 1)]
|
||||
n_shift = n_ring - len(r_bits)
|
||||
tmp = a + sint.bit_compose(r_bits)
|
||||
masked = (tmp << n_shift).reveal()
|
||||
shifted = (masked << 1 >> (n_shift + m + 1))
|
||||
overflow = r_bits[-1].bit_xor(masked >> (n_ring - 1))
|
||||
res = shifted - sint.bit_compose(r_bits[m:k]) + (overflow << (k - m))
|
||||
return res
|
||||
|
||||
def TruncPrField(a, k, m, kappa=None):
|
||||
if kappa is None:
|
||||
@@ -504,27 +519,26 @@ def TruncPrField(a, k, m, kappa=None):
|
||||
d = (a - a_prime) / two_to_m
|
||||
return d
|
||||
|
||||
def SDiv(a, b, l, kappa):
|
||||
def SDiv(a, b, l, kappa, round_nearest=False):
|
||||
theta = int(ceil(log(l / 3.5) / log(2)))
|
||||
alpha = two_power(2*l)
|
||||
beta = 1 / types.cint(two_power(l))
|
||||
w = types.cint(int(2.9142 * two_power(l))) - 2 * b
|
||||
x = alpha - b * w
|
||||
y = a * w
|
||||
y = TruncPr(y, 2 * l, l, kappa)
|
||||
y = y.round(2 * l + 1, l, kappa, round_nearest)
|
||||
x2 = types.sint()
|
||||
comparison.Mod2m(x2, x, 2 * l + 1, l, kappa, False)
|
||||
x1 = (x - x2) * beta
|
||||
x1 = comparison.TruncZeroes(x - x2, 2 * l + 1, l, True)
|
||||
for i in range(theta-1):
|
||||
y = y * (x1 + two_power(l)) + TruncPr(y * x2, 2 * l, l, kappa)
|
||||
y = TruncPr(y, 2 * l + 1, l + 1, kappa)
|
||||
x = x1 * x2 + TruncPr(x2**2, 2 * l + 1, l + 1, kappa)
|
||||
x = x1 * x1 + TruncPr(x, 2 * l + 1, l - 1, kappa)
|
||||
y = y * (x1 + two_power(l)) + (y * x2).round(2 * l, l, kappa, round_nearest)
|
||||
y = y.round(2 * l + 1, l + 1, kappa, round_nearest)
|
||||
x = x1 * x2 + (x2**2).round(2 * l + 1, l + 1, kappa, round_nearest)
|
||||
x = x1 * x1 + x.round(2 * l + 1, l - 1, kappa, round_nearest)
|
||||
x2 = types.sint()
|
||||
comparison.Mod2m(x2, x, 2 * l, l, kappa, False)
|
||||
x1 = (x - x2) * beta
|
||||
y = y * (x1 + two_power(l)) + TruncPr(y * x2, 2 * l, l, kappa)
|
||||
y = TruncPr(y, 2 * l + 1, l - 1, kappa)
|
||||
x1 = comparison.TruncZeroes(x - x2, 2 * l + 1, l, True)
|
||||
y = y * (x1 + two_power(l)) + (y * x2).round(2 * l, l, kappa, round_nearest)
|
||||
y = y.round(2 * l + 1, l - 1, kappa, round_nearest)
|
||||
return y
|
||||
|
||||
def SDiv_mono(a, b, l, kappa):
|
||||
|
||||
@@ -933,13 +933,6 @@ class print_reg_plain(base.IOInstruction):
|
||||
code = base.opcodes['PRINTREGPLAIN']
|
||||
arg_format = ['c']
|
||||
|
||||
|
||||
@base.vectorize
|
||||
class print_float_plain(base.IOInstruction):
|
||||
__slots__ = []
|
||||
code = base.opcodes['PRINTFLOATPLAIN']
|
||||
arg_format = ['c', 'c', 'c', 'c']
|
||||
|
||||
class print_int(base.IOInstruction):
|
||||
r""" Print only the value of register \verb|ci| to stdout. """
|
||||
__slots__ = []
|
||||
@@ -1358,10 +1351,7 @@ class muls(base.VarArgsInstruction, base.DataInstruction):
|
||||
data_type = 'triple'
|
||||
|
||||
def get_repeat(self):
|
||||
if program.options.ring:
|
||||
return 0
|
||||
else:
|
||||
return len(self.args) / 3
|
||||
return len(self.args) / 3
|
||||
|
||||
# def expand(self):
|
||||
# s = [program.curr_block.new_reg('s') for i in range(9)]
|
||||
@@ -1378,6 +1368,73 @@ class muls(base.VarArgsInstruction, base.DataInstruction):
|
||||
# adds(s[8], s[7], s[6])
|
||||
# addm(self.args[0], s[8], c[2])
|
||||
|
||||
@base.gf2n
|
||||
class mulrs(base.VarArgsInstruction, base.DataInstruction):
|
||||
""" Secret multiplication $s_i = s_j \cdot s_k$. """
|
||||
__slots__ = []
|
||||
code = base.opcodes['MULRS']
|
||||
arg_format = tools.cycle(['int','sw','s','s'])
|
||||
data_type = 'triple'
|
||||
is_vec = lambda self: True
|
||||
|
||||
def __init__(self, res, x, y):
|
||||
assert y.size == 1
|
||||
assert res.size == x.size
|
||||
base.Instruction.__init__(self, res.size, res, x, y)
|
||||
|
||||
def get_repeat(self):
|
||||
return sum(self.args[::4])
|
||||
|
||||
def get_def(self):
|
||||
return sum((arg.get_all() for arg in self.args[1::4]), [])
|
||||
|
||||
def get_used(self):
|
||||
return sum((arg.get_all()
|
||||
for arg in self.args[2::4] + self.args[3::4]), [])
|
||||
|
||||
@base.gf2n
|
||||
class dotprods(base.VarArgsInstruction, base.DataInstruction):
|
||||
""" Secret dot product. """
|
||||
__slots__ = []
|
||||
code = base.opcodes['DOTPRODS']
|
||||
data_type = 'triple'
|
||||
|
||||
def __init__(self, *args):
|
||||
flat_args = []
|
||||
for i in range(0, len(args), 3):
|
||||
res, x, y = args[i:i+3]
|
||||
assert len(x) == len(y)
|
||||
flat_args += [2 * len(x) + 2, res]
|
||||
for x, y in zip(x, y):
|
||||
flat_args += [x, y]
|
||||
base.Instruction.__init__(self, *flat_args)
|
||||
|
||||
@property
|
||||
def arg_format(self):
|
||||
field = 'g' if self.is_gf2n() else ''
|
||||
for i in self.bases():
|
||||
yield 'int'
|
||||
yield 's' + field + 'w'
|
||||
for j in range(self.args[i] - 2):
|
||||
yield 's' + field
|
||||
|
||||
def bases(self):
|
||||
i = 0
|
||||
while i < len(self.args):
|
||||
yield i
|
||||
i += self.args[i]
|
||||
|
||||
def get_repeat(self):
|
||||
return sum(self.args[i] / 2 for i in self.bases())
|
||||
|
||||
def get_def(self):
|
||||
return [self.args[i + 1] for i in self.bases()]
|
||||
|
||||
def get_used(self):
|
||||
for i in self.bases():
|
||||
for reg in self.args[i + 2:i + self.args[i]]:
|
||||
yield reg
|
||||
|
||||
###
|
||||
### CISC-style instructions
|
||||
###
|
||||
|
||||
@@ -87,6 +87,8 @@ opcodes = dict(
|
||||
# Open
|
||||
OPEN = 0xA5,
|
||||
MULS = 0xA6,
|
||||
MULRS = 0xA7,
|
||||
DOTPRODS = 0xA8,
|
||||
# Data access
|
||||
TRIPLE = 0x50,
|
||||
BIT = 0x51,
|
||||
@@ -177,19 +179,14 @@ def int_to_bytes(x):
|
||||
return [(x >> 8*i) % 256 for i in (3,2,1,0)]
|
||||
|
||||
|
||||
global_vector_size = 1
|
||||
global_vector_size_depth = 0
|
||||
global_vector_size_stack = []
|
||||
global_instruction_type_stack = ['modp']
|
||||
|
||||
def set_global_vector_size(size):
|
||||
global global_vector_size, global_vector_size_depth
|
||||
if size == 1:
|
||||
stack = global_vector_size_stack
|
||||
if size == 1 and not stack:
|
||||
return
|
||||
if global_vector_size == 1 or global_vector_size == size:
|
||||
global_vector_size = size
|
||||
global_vector_size_depth += 1
|
||||
else:
|
||||
raise CompilerError('Cannot set global vector size when already set')
|
||||
stack.append(size)
|
||||
|
||||
def set_global_instruction_type(t):
|
||||
if t == 'modp' or t == 'gf2n':
|
||||
@@ -198,17 +195,19 @@ def set_global_instruction_type(t):
|
||||
raise CompilerError('Invalid type %s for setting global instruction type')
|
||||
|
||||
def reset_global_vector_size():
|
||||
global global_vector_size, global_vector_size_depth
|
||||
if global_vector_size_depth > 0:
|
||||
global_vector_size_depth -= 1
|
||||
if global_vector_size_depth == 0:
|
||||
global_vector_size = 1
|
||||
stack = global_vector_size_stack
|
||||
if global_vector_size_stack:
|
||||
stack.pop()
|
||||
|
||||
def reset_global_instruction_type():
|
||||
global_instruction_type_stack.pop()
|
||||
|
||||
def get_global_vector_size():
|
||||
return global_vector_size
|
||||
stack = global_vector_size_stack
|
||||
if stack:
|
||||
return stack[-1]
|
||||
else:
|
||||
return 1
|
||||
|
||||
def get_global_instruction_type():
|
||||
return global_instruction_type_stack[-1]
|
||||
@@ -243,10 +242,17 @@ def vectorize(instruction, global_dict=None):
|
||||
|
||||
@functools.wraps(instruction)
|
||||
def maybe_vectorized_instruction(*args, **kwargs):
|
||||
if global_vector_size == 1:
|
||||
size = get_global_vector_size()
|
||||
for arg in args:
|
||||
try:
|
||||
size = arg.size
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if size == 1:
|
||||
return instruction(*args, **kwargs)
|
||||
else:
|
||||
return Vectorized_Instruction(global_vector_size, *args, **kwargs)
|
||||
return Vectorized_Instruction(size, *args, **kwargs)
|
||||
maybe_vectorized_instruction.vec_ins = Vectorized_Instruction
|
||||
maybe_vectorized_instruction.std_ins = instruction
|
||||
|
||||
@@ -287,6 +293,8 @@ def gf2n(instruction):
|
||||
else:
|
||||
__format.append(__f[0] + 'g' + __f[1:])
|
||||
arg_format[:] = __format
|
||||
elif isinstance(arg_format, property):
|
||||
pass
|
||||
else:
|
||||
for __f in arg_format.args:
|
||||
reformat(__f)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from Compiler.types import cint,sint,cfix,sfix,sfloat,MPCThread,Array,MemValue,cgf2n,sgf2n,_number,_mem,_register,regint,Matrix,_types, cfloat
|
||||
from Compiler.types import cint,sint,cfix,sfix,sfloat,MPCThread,Array,MemValue,cgf2n,sgf2n,_number,_mem,_register,regint,Matrix,_types, cfloat, _single
|
||||
from Compiler.instructions import *
|
||||
from Compiler.util import tuplify,untuplify
|
||||
from Compiler import instructions,instructions_base,comparison,program,util
|
||||
@@ -98,6 +98,7 @@ def print_ln_if(cond, s):
|
||||
if cond:
|
||||
print_ln(s)
|
||||
else:
|
||||
s += ' ' * ((len(s) + 3) % 4)
|
||||
s += '\n'
|
||||
while s:
|
||||
cond.print_if(s[:4])
|
||||
@@ -816,7 +817,7 @@ def map_reduce_single(n_parallel, n_loops, initializer, reducer, mem_state=None)
|
||||
n_parallel = n_parallel or 1
|
||||
if mem_state is None:
|
||||
# default to list of MemValues to allow varying types
|
||||
mem_state = [type(x).MemValue(x) for x in initializer()]
|
||||
mem_state = [MemValue(x) for x in initializer()]
|
||||
use_array = False
|
||||
else:
|
||||
# use Arrays for multithread version
|
||||
|
||||
@@ -68,6 +68,10 @@ class Program(object):
|
||||
Compiler.instructions.gasm_open_class, \
|
||||
Compiler.instructions.muls_class, \
|
||||
Compiler.instructions.gmuls_class, \
|
||||
Compiler.instructions.mulrs_class, \
|
||||
Compiler.instructions.gmulrs, \
|
||||
Compiler.instructions.dotprods_class, \
|
||||
Compiler.instructions.gdotprods, \
|
||||
Compiler.instructions.asm_input_class, \
|
||||
Compiler.instructions.gasm_input_class]
|
||||
import Compiler.GC.instructions as gc
|
||||
@@ -433,6 +437,7 @@ class Tape:
|
||||
self.alloc_pool = scope.alloc_pool
|
||||
else:
|
||||
self.alloc_pool = defaultdict(set)
|
||||
self.purged = False
|
||||
|
||||
def new_reg(self, reg_type, size=None):
|
||||
return self.parent.new_reg(reg_type, size=size)
|
||||
@@ -468,6 +473,23 @@ class Tape:
|
||||
offset = self.get_offset(self.exit_block)
|
||||
self.exit_condition.set_relative_jump(offset)
|
||||
#print 'Basic block %d jumps to %d (%d)' % (next_block_index, jump_index, offset)
|
||||
|
||||
def purge(self):
|
||||
relevant = lambda inst: inst.add_usage.__func__ is not \
|
||||
Compiler.instructions_base.Instruction.add_usage.__func__
|
||||
self.usage_instructions = filter(relevant, self.instructions)
|
||||
del self.instructions
|
||||
del self.defined_registers
|
||||
self.purged = True
|
||||
|
||||
def add_usage(self, req_node):
|
||||
if self.purged:
|
||||
instructions = self.usage_instructions
|
||||
else:
|
||||
instructions = self.instructions
|
||||
for inst in instructions:
|
||||
inst.add_usage(req_node)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@@ -507,6 +529,8 @@ class Tape:
|
||||
self.outfile = self.program.programs_dir + '/Bytecode/' + self.name + '.bc'
|
||||
|
||||
def purge(self):
|
||||
for block in self.basicblocks:
|
||||
block.purge()
|
||||
self._is_empty = (len(self.basicblocks) == 0)
|
||||
del self.reg_values
|
||||
del self.basicblocks
|
||||
@@ -772,8 +796,7 @@ class Tape:
|
||||
def aggregate(self, *args):
|
||||
self.num = Tape.ReqNum()
|
||||
for block in self.blocks:
|
||||
for inst in block.instructions:
|
||||
inst.add_usage(self)
|
||||
block.add_usage(self)
|
||||
res = reduce(lambda x,y: x + y.aggregate(self.name),
|
||||
self.children, self.num)
|
||||
return res
|
||||
@@ -842,7 +865,7 @@ class Tape:
|
||||
if size is None:
|
||||
size = Compiler.instructions_base.get_global_vector_size()
|
||||
self.size = size
|
||||
if i:
|
||||
if i is not None:
|
||||
self.i = i
|
||||
else:
|
||||
self.i = program.reg_counter[reg_type]
|
||||
@@ -878,23 +901,29 @@ class Tape:
|
||||
raise CompilerError('Cannot reset size of vector register')
|
||||
|
||||
def set_vectorbase(self, vectorbase):
|
||||
if self.vectorbase != self:
|
||||
if self.vectorbase is not self:
|
||||
raise CompilerError('Cannot assign one register' \
|
||||
'to several vectors')
|
||||
self.vectorbase = vectorbase
|
||||
|
||||
def _new_by_number(self, i):
|
||||
return Tape.Register(self.reg_type, self.program, size=1, i=i)
|
||||
|
||||
def create_vector_elements(self):
|
||||
if self.vector:
|
||||
return
|
||||
elif self.size == 1:
|
||||
self.vector = [self]
|
||||
return
|
||||
self.vector = [self]
|
||||
for i in range(1,self.size):
|
||||
reg = Tape.Register(self.reg_type, self.program, size=1, i=self.i+i)
|
||||
self.vector = []
|
||||
for i in range(self.size):
|
||||
reg = self._new_by_number(self.i + i)
|
||||
reg.set_vectorbase(self)
|
||||
self.vector.append(reg)
|
||||
|
||||
def get_all(self):
|
||||
return self.vector or [self]
|
||||
|
||||
def __getitem__(self, index):
|
||||
if not self.vector:
|
||||
self.create_vector_elements()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,11 +27,11 @@ def greater_than(a, b, bits):
|
||||
else:
|
||||
return a.greater_than(b, bits)
|
||||
|
||||
def pow2(a, bits):
|
||||
if isinstance(a, int):
|
||||
def pow2_value(a, bit_length=None, security=None):
|
||||
if is_constant_float(a):
|
||||
return 2**a
|
||||
else:
|
||||
return a.pow2(bits)
|
||||
return a.pow2(bit_length, security)
|
||||
|
||||
def mod2m(a, b, bits, signed):
|
||||
if isinstance(a, int):
|
||||
@@ -95,7 +95,16 @@ def cond_swap(cond, a, b):
|
||||
|
||||
def log2(x):
|
||||
#print 'Compute log2 of', x
|
||||
return int(math.ceil(math.log(x, 2)))
|
||||
if is_constant_float(x):
|
||||
return int(math.ceil(math.log(x, 2)))
|
||||
else:
|
||||
return x.log2()
|
||||
|
||||
def round_to_int(x):
|
||||
if is_constant_float(x):
|
||||
return int(round(x))
|
||||
else:
|
||||
return x.round_to_int()
|
||||
|
||||
def tree_reduce(function, sequence):
|
||||
sequence = list(sequence)
|
||||
@@ -165,3 +174,9 @@ def long_one(x):
|
||||
except:
|
||||
pass
|
||||
return 1
|
||||
|
||||
def expand(x, size):
|
||||
try:
|
||||
return x.expand_to_vector(size)
|
||||
except AttributeError:
|
||||
return x
|
||||
|
||||
@@ -340,12 +340,14 @@ void MultiEncCommit<FD>::add_ciphertexts(vector<Ciphertext>& ciphertexts,
|
||||
|
||||
template class SimpleEncCommitBase<gfp, FFT_Data, bigint>;
|
||||
template class SimpleEncCommit<gfp, FFT_Data, bigint>;
|
||||
template class SimpleEncCommitFactory<FFT_Data>;
|
||||
template class SummingEncCommit<FFT_Data>;
|
||||
template class NonInteractiveProofSimpleEncCommit<FFT_Data>;
|
||||
template class MultiEncCommit<FFT_Data>;
|
||||
|
||||
template class SimpleEncCommitBase<gf2n_short, P2Data, int>;
|
||||
template class SimpleEncCommit<gf2n_short, P2Data, int>;
|
||||
template class SimpleEncCommitFactory<P2Data>;
|
||||
template class SummingEncCommit<P2Data>;
|
||||
template class NonInteractiveProofSimpleEncCommit<P2Data>;
|
||||
template class MultiEncCommit<P2Data>;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "Tools/benchmarking.h"
|
||||
|
||||
#include "Auth/fake-stuff.hpp"
|
||||
#include "Processor/Data_Files.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#include "Program.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "ThreadMaster.hpp"
|
||||
#include "Auth/MaliciousRepMC.hpp"
|
||||
#include "Processor/Replicated.hpp"
|
||||
|
||||
#include "Processor/Machine.hpp"
|
||||
#include "Processor/Instruction.hpp"
|
||||
|
||||
namespace GC
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Math/Setup.h"
|
||||
|
||||
#include "Auth/MaliciousRepMC.hpp"
|
||||
#include "Processor/Data_Files.hpp"
|
||||
|
||||
namespace GC
|
||||
{
|
||||
@@ -61,7 +62,7 @@ void MaliciousRepThread::and_(Processor<MaliciousRepSecret>& processor,
|
||||
int n_bits = args[i];
|
||||
int left = args[i + 2];
|
||||
int right = args[i + 3];
|
||||
triples.push_back({0});
|
||||
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;
|
||||
|
||||
@@ -13,7 +13,7 @@ union matrix32x8
|
||||
__m256i whole;
|
||||
octet rows[32];
|
||||
|
||||
matrix32x8(__m256i x = _mm256_setzero_si256()) : whole(x) {}
|
||||
matrix32x8(const __m256i& x = _mm256_setzero_si256()) : whole(x) {}
|
||||
|
||||
matrix32x8(square64& input, int x, int y)
|
||||
{
|
||||
@@ -23,6 +23,7 @@ union matrix32x8
|
||||
|
||||
void transpose(square64& output, int x, int y)
|
||||
{
|
||||
#ifdef __AVX2__
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int row = _mm256_movemask_epi8(whole);
|
||||
@@ -31,6 +32,10 @@ union matrix32x8
|
||||
// _mm_movemask_epi8 uses most significant bit, hence +7-j
|
||||
output.halfrows[8*x+7-j][y] = row;
|
||||
}
|
||||
#else
|
||||
(void) output, (void) x, (void) y;
|
||||
throw runtime_error("need to compile with AVX2 support");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,8 +56,10 @@ case I: \
|
||||
HIGHS = _mm256_unpackhi_epi##I(A, B); \
|
||||
break;
|
||||
|
||||
void zip(int chunk_size, __m256i& lows, __m256i& highs, __m256i a, __m256i b)
|
||||
void zip(int chunk_size, __m256i& lows, __m256i& highs,
|
||||
const __m256i& a, const __m256i& b)
|
||||
{
|
||||
#ifdef __AVX2__
|
||||
switch (chunk_size)
|
||||
{
|
||||
ZIP_CASE(8, lows, highs, a, b);
|
||||
@@ -67,6 +74,10 @@ void zip(int chunk_size, __m256i& lows, __m256i& highs, __m256i a, __m256i b)
|
||||
default:
|
||||
throw invalid_argument("not supported");
|
||||
}
|
||||
#else
|
||||
(void) chunk_size, (void) lows, (void) highs, (void) a, (void) b;
|
||||
throw runtime_error("need to compile with AVX2 support");
|
||||
#endif
|
||||
}
|
||||
|
||||
void square64::transpose(int n_rows, int n_cols)
|
||||
|
||||
49
Machines/Rep.cpp
Normal file
49
Machines/Rep.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Rep.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Processor/Data_Files.hpp"
|
||||
#include "Processor/Instruction.hpp"
|
||||
#include "Processor/Machine.hpp"
|
||||
|
||||
template<>
|
||||
Preprocessing<Rep3Share<gfp>>* Preprocessing<Rep3Share<gfp>>::get_live_prep(
|
||||
SubProcessor<Rep3Share<gfp>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<Rep3Share<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<Rep3Share<gf2n>>* Preprocessing<Rep3Share<gf2n>>::get_live_prep(
|
||||
SubProcessor<Rep3Share<gf2n>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<Rep3Share<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<Rep3Share<Integer>>* Preprocessing<Rep3Share<Integer>>::get_live_prep(
|
||||
SubProcessor<Rep3Share<Integer>>* proc)
|
||||
{
|
||||
return new ReplicatedRingPrep<Rep3Share<Integer>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousRep3Share<gfp>>* Preprocessing<MaliciousRep3Share<gfp>>::get_live_prep(
|
||||
SubProcessor<MaliciousRep3Share<gfp>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousRep3Share<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousRep3Share<gf2n>>* Preprocessing<MaliciousRep3Share<gf2n>>::get_live_prep(
|
||||
SubProcessor<MaliciousRep3Share<gf2n>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousRep3Share<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template class Machine<Rep3Share<Integer>, Rep3Share<gf2n>>;
|
||||
template class Machine<Rep3Share<gfp>, Rep3Share<gf2n>>;
|
||||
template class Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>;
|
||||
6
Machines/SPDZ.cpp
Normal file
6
Machines/SPDZ.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
#include "Processor/Data_Files.hpp"
|
||||
#include "Processor/Instruction.hpp"
|
||||
#include "Processor/Machine.hpp"
|
||||
|
||||
template class Machine<sgfp, Share<gf2n>>;
|
||||
@@ -3,13 +3,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ShamirMachine.h"
|
||||
#include <Machines/ShamirMachine.h>
|
||||
#include "Math/ShamirShare.h"
|
||||
#include "Math/MaliciousShamirShare.h"
|
||||
#include "Math/gfp.h"
|
||||
#include "Math/gf2n.h"
|
||||
|
||||
#include "ReplicatedMachine.hpp"
|
||||
#include "Processor/ReplicatedMachine.hpp"
|
||||
|
||||
#include "Processor/Data_Files.hpp"
|
||||
#include "Processor/Instruction.hpp"
|
||||
#include "Processor/Machine.hpp"
|
||||
|
||||
ShamirMachine* ShamirMachine::singleton = 0;
|
||||
|
||||
@@ -64,5 +68,38 @@ ShamirMachineSpec<T>::ShamirMachineSpec(int argc, const char** argv) :
|
||||
ReplicatedMachine<T<gfp>, T<gf2n>>(argc, argv, "shamir", opt, nparties);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<ShamirShare<gfp>>* Preprocessing<ShamirShare<gfp>>::get_live_prep(
|
||||
SubProcessor<ShamirShare<gfp>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<ShamirShare<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<ShamirShare<gf2n>>* Preprocessing<ShamirShare<gf2n>>::get_live_prep(
|
||||
SubProcessor<ShamirShare<gf2n>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<ShamirShare<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousShamirShare<gfp>>* Preprocessing<MaliciousShamirShare<gfp>>::get_live_prep(
|
||||
SubProcessor<MaliciousShamirShare<gfp>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousShamirShare<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousShamirShare<gf2n>>* Preprocessing<MaliciousShamirShare<gf2n>>::get_live_prep(
|
||||
SubProcessor<MaliciousShamirShare<gf2n>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousShamirShare<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template class ShamirMachineSpec<ShamirShare>;
|
||||
template class ShamirMachineSpec<MaliciousShamirShare>;
|
||||
|
||||
template class Machine<ShamirShare<gfp>, ShamirShare<gf2n>>;
|
||||
template class Machine<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>;
|
||||
@@ -3,8 +3,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROCESSOR_SHAMIRMACHINE_H_
|
||||
#define PROCESSOR_SHAMIRMACHINE_H_
|
||||
#ifndef MACHINES_SHAMIRMACHINE_H_
|
||||
#define MACHINES_SHAMIRMACHINE_H_
|
||||
|
||||
#include "Tools/ezOptionParser.h"
|
||||
|
||||
@@ -31,4 +31,4 @@ public:
|
||||
ShamirMachineSpec(int argc, const char** argv);
|
||||
};
|
||||
|
||||
#endif /* PROCESSOR_SHAMIRMACHINE_H_ */
|
||||
#endif /* MACHINES_SHAMIRMACHINE_H_ */
|
||||
78
Makefile
78
Makefile
@@ -28,22 +28,25 @@ 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)
|
||||
BMR = $(patsubst %.cpp,%.o,$(wildcard BMR/*.cpp BMR/network/*.cpp)) $(COMMON) Processor/BaseMachine.o Processor/ProcessorBase.o
|
||||
|
||||
|
||||
LIB = libSPDZ.a
|
||||
LIBHM = libhm.a
|
||||
LIBSIMPLEOT = SimpleOT/libsimpleot.a
|
||||
|
||||
# used for dependency generation
|
||||
OBJS = $(BMR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(YAO) $(COMPLETE)
|
||||
OBJS = $(BMR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(YAO) $(COMPLETE) $(patsubst %.cpp,%.o,$(wildcard Machines/*.cpp))
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
|
||||
|
||||
all: gen_input online offline externalIO yao replicated shamir
|
||||
|
||||
ifeq ($(USE_GF2N_LONG),1)
|
||||
ifneq ($(OS), Darwin)
|
||||
all: bmr
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_NTL),1)
|
||||
all: overdrive she-offline
|
||||
@@ -78,21 +81,40 @@ 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
|
||||
tldr:
|
||||
-echo ARCH = -march=native >> CONFIG.mine
|
||||
$(MAKE) malicious-rep-field-party.x Setup.x
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
tldr: mac-setup
|
||||
else
|
||||
tldr: mpir
|
||||
endif
|
||||
|
||||
shamir: shamir-party.x malicious-shamir-party.x galois-degree.x
|
||||
|
||||
Fake-Offline.x: Fake-Offline.cpp $(COMMON) $(PROCESSOR)
|
||||
$(CXX) $(CFLAGS) -o $@ Fake-Offline.cpp $(COMMON) $(PROCESSOR) $(LDLIBS)
|
||||
$(LIBHM): Machines/Rep.o Machines/ShamirMachine.o $(PROCESSOR) $(COMMON)
|
||||
$(AR) -csr $@ $^
|
||||
|
||||
static/%.x: %.cpp $(LIBHM) $(LIBSIMPLEOT)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ -Wl,-Map=$<.map -Wl,-Bstatic -static-libgcc -static-libstdc++ $(BOOST) $(LDLIBS) -Wl,-Bdynamic -ldl
|
||||
|
||||
static-dir:
|
||||
@ mkdir static 2> /dev/null; true
|
||||
|
||||
static-hm: static-dir $(patsubst %.cpp, static/%.x, $(wildcard *ring*.cpp *field*.cpp *shamir*.cpp ))
|
||||
|
||||
Fake-Offline.x: Fake-Offline.cpp $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(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)
|
||||
$(CXX) $(CFLAGS) Check-Offline.cpp -o Check-Offline.x $(COMMON) $(LDLIBS)
|
||||
|
||||
Server.x: Server.cpp $(COMMON)
|
||||
$(CXX) $(CFLAGS) Server.cpp -o Server.x $(COMMON) $(LDLIBS)
|
||||
|
||||
Player-Online.x: Player-Online.cpp $(COMMON) $(PROCESSOR)
|
||||
$(CXX) $(CFLAGS) Player-Online.cpp -o Player-Online.x $(COMMON) $(PROCESSOR) $(LDLIBS)
|
||||
Player-Online.x: Player-Online.cpp Machines/SPDZ.o $(COMMON) $(PROCESSOR)
|
||||
$(CXX) $(CFLAGS) -o Player-Online.x $^ $(LDLIBS)
|
||||
|
||||
Setup.x: Setup.cpp $(COMMON)
|
||||
$(CXX) $(CFLAGS) Setup.cpp -o Setup.x $(COMMON) $(LDLIBS)
|
||||
@@ -134,13 +156,13 @@ endif
|
||||
bmr-clean:
|
||||
-rm BMR/*.o BMR/*/*.o GC/*.o
|
||||
|
||||
client-setup.x: client-setup.cpp $(COMMON) $(PROCESSOR)
|
||||
client-setup.x: client-setup.cpp $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
bankers-bonus-client.x: ExternalIO/bankers-bonus-client.cpp $(COMMON) $(PROCESSOR)
|
||||
bankers-bonus-client.x: ExternalIO/bankers-bonus-client.cpp $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
bankers-bonus-commsec-client.x: ExternalIO/bankers-bonus-commsec-client.cpp $(COMMON) $(PROCESSOR)
|
||||
bankers-bonus-commsec-client.x: ExternalIO/bankers-bonus-commsec-client.cpp $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
ifeq ($(USE_NTL),1)
|
||||
@@ -172,19 +194,19 @@ replicated-bin-party.x: $(COMMON) $(GC) replicated-bin-party.cpp
|
||||
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)
|
||||
replicated-ring-party.x: replicated-ring-party.cpp Machines/Rep.o $(PROCESSOR) $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
replicated-field-party.x: replicated-field-party.cpp $(PROCESSOR) $(COMMON)
|
||||
replicated-field-party.x: replicated-field-party.cpp Machines/Rep.o $(PROCESSOR) $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
malicious-rep-field-party.x: malicious-rep-field-party.cpp $(PROCESSOR) $(COMMON)
|
||||
malicious-rep-field-party.x: malicious-rep-field-party.cpp Machines/Rep.o $(PROCESSOR) $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
shamir-party.x: shamir-party.cpp $(PROCESSOR) $(COMMON)
|
||||
shamir-party.x: shamir-party.cpp Machines/ShamirMachine.o $(PROCESSOR) $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
malicious-shamir-party.x: malicious-shamir-party.cpp $(PROCESSOR) $(COMMON)
|
||||
malicious-shamir-party.x: malicious-shamir-party.cpp Machines/ShamirMachine.o $(PROCESSOR) $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
$(LIBSIMPLEOT): SimpleOT/Makefile
|
||||
@@ -196,15 +218,31 @@ OT/BaseOT.o: SimpleOT/Makefile
|
||||
SimpleOT/Makefile:
|
||||
git submodule update --init SimpleOT
|
||||
|
||||
.PHONY: mpir
|
||||
mpir:
|
||||
.PHONY: mpir-setup mpir-global mpir
|
||||
mpir-setup:
|
||||
git submodule update --init mpir
|
||||
cd mpir; \
|
||||
autoreconf -i; \
|
||||
autoreconf -i; \
|
||||
autoreconf -i
|
||||
- $(MAKE) -C mpir clean
|
||||
|
||||
mpir-global: mpir-setup
|
||||
cd mpir; \
|
||||
./configure --enable-cxx;
|
||||
$(MAKE) -C mpir
|
||||
sudo $(MAKE) -C mpir install
|
||||
|
||||
mpir: mpir-setup
|
||||
cd mpir; \
|
||||
./configure --enable-cxx --prefix=$(CURDIR)/local
|
||||
$(MAKE) -C mpir install
|
||||
-echo MY_CFLAGS += -I./local/include >> CONFIG.mine
|
||||
-echo MY_LDLIBS += -Wl,-rpath -Wl,./local/lib -L./local/lib >> CONFIG.mine
|
||||
|
||||
mac-setup:
|
||||
brew install openssl boost libsodium mpir yasm
|
||||
-echo MY_CFLAGS += -I/usr/local/opt/openssl/include >> CONFIG.mine
|
||||
-echo MY_LDLIBS += -L/usr/local/opt/openssl/lib >> CONFIG.mine
|
||||
|
||||
clean:
|
||||
-rm */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o
|
||||
-rm */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o static/*.x
|
||||
|
||||
@@ -17,6 +17,8 @@ public:
|
||||
static char type_char() { return 'B'; }
|
||||
static DataFieldType field_type() { return DATA_GF2; }
|
||||
|
||||
static bool allows(Dtype dtype) { return dtype == DATA_TRIPLE or dtype == DATA_BIT; }
|
||||
|
||||
BitVec() {}
|
||||
BitVec(long a) : IntBase(a) {}
|
||||
BitVec(const IntBase& a) : IntBase(a) {}
|
||||
|
||||
@@ -27,6 +27,8 @@ public:
|
||||
|
||||
static void init_default(int lgp) { (void)lgp; }
|
||||
|
||||
static bool allows(Dtype type) { return type <= DATA_BIT; }
|
||||
|
||||
IntBase() { a = 0; }
|
||||
IntBase(long a) : a(a) {}
|
||||
|
||||
@@ -79,7 +81,7 @@ class Integer : public IntBase
|
||||
typedef Integer clear;
|
||||
|
||||
static char type_char() { return 'R'; }
|
||||
static DataFieldType field_type() { return DATA_INT64; }
|
||||
static DataFieldType field_type() { return DATA_INT; }
|
||||
|
||||
static void reqbl(int n);
|
||||
|
||||
|
||||
@@ -83,6 +83,11 @@ public:
|
||||
*this = Rep3Share(aa, my_num) - S;
|
||||
}
|
||||
|
||||
clear local_mul(const Rep3Share& other) const
|
||||
{
|
||||
return (*this)[0] * other.sum() + (*this)[1] * other[0];
|
||||
}
|
||||
|
||||
void mul_by_bit(const Rep3Share& x, const T& y)
|
||||
{
|
||||
(void) x, (void) y;
|
||||
|
||||
@@ -196,6 +196,7 @@ inline void Zp_Data::Sub(mp_limb_t* ans,const mp_limb_t* x,const mp_limb_t* y) c
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __BMI2__
|
||||
template <int T>
|
||||
inline void Zp_Data::Mont_Mult_(mp_limb_t* z,const mp_limb_t* x,const mp_limb_t* y) const
|
||||
{
|
||||
@@ -219,17 +220,20 @@ inline void Zp_Data::Mont_Mult_(mp_limb_t* z,const mp_limb_t* x,const mp_limb_t*
|
||||
else
|
||||
{ inline_mpn_copyi(z,ans+T,T); }
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void Zp_Data::Mont_Mult(mp_limb_t* z,const mp_limb_t* x,const mp_limb_t* y) const
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
#ifdef __BMI2__
|
||||
case 2:
|
||||
Mont_Mult_<2>(z, x, y);
|
||||
break;
|
||||
case 1:
|
||||
Mont_Mult_<1>(z, x, y);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
Mont_Mult_variable(z, x, y);
|
||||
break;
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#define MATH_FIELD_TYPES_H_
|
||||
|
||||
|
||||
enum DataFieldType { DATA_MODP, DATA_GF2N, DATA_GF2, DATA_INT64, N_DATA_FIELD_TYPE };
|
||||
enum DataFieldType { DATA_INT, DATA_GF2N, DATA_GF2, N_DATA_FIELD_TYPE };
|
||||
|
||||
enum Dtype { DATA_TRIPLE, DATA_SQUARE, DATA_BIT, DATA_INVERSE, DATA_BITTRIPLE, DATA_BITGF2NTRIPLE, N_DTYPE };
|
||||
|
||||
#endif /* MATH_FIELD_TYPES_H_ */
|
||||
|
||||
@@ -91,7 +91,11 @@ void gf2n_short::init_field(int nn)
|
||||
|
||||
mask=(1ULL<<n)-1;
|
||||
|
||||
#ifdef __PCLMUL__
|
||||
useC=(Check_CPU_support_AES()==0);
|
||||
#else
|
||||
useC = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +226,7 @@ void gf2n_short::mul(const gf2n_short& x,const gf2n_short& y)
|
||||
}
|
||||
else
|
||||
{ /* Use Intel Instructions */
|
||||
#ifdef __PCLMUL__
|
||||
__m128i xx,yy,zz;
|
||||
uint64_t c[] __attribute__((aligned (16))) = { 0,0 };
|
||||
xx=_mm_set1_epi64x(x.a);
|
||||
@@ -230,6 +235,9 @@ void gf2n_short::mul(const gf2n_short& x,const gf2n_short& y)
|
||||
_mm_store_si128((__m128i*)c,zz);
|
||||
lo=c[0];
|
||||
hi=c[1];
|
||||
#else
|
||||
throw runtime_error("need to compile with PCLMUL support");
|
||||
#endif
|
||||
}
|
||||
|
||||
reduce(hi,lo);
|
||||
|
||||
@@ -80,6 +80,8 @@ class gf2n_short
|
||||
|
||||
static int default_length() { return 40; }
|
||||
|
||||
static bool allows(Dtype type) { (void) type; return true; }
|
||||
|
||||
word get() const { return a; }
|
||||
word get_word() const { return a; }
|
||||
|
||||
|
||||
@@ -31,9 +31,13 @@ public:
|
||||
int128(const word& upper, const word& lower) : a(_mm_set_epi64x(upper, lower)) { }
|
||||
|
||||
word get_lower() const { return (word)_mm_cvtsi128_si64(a); }
|
||||
word get_upper() const { return _mm_extract_epi64(a, 1); }
|
||||
word get_upper() const { return _mm_cvtsi128_si64(_mm_unpackhi_epi64(a, a)); }
|
||||
|
||||
#ifdef __SSE41__
|
||||
bool operator==(const int128& other) const { return _mm_test_all_zeros(a ^ other.a, a ^ other.a); }
|
||||
#else
|
||||
bool operator==(const int128& other) const { return get_lower() == other.get_lower() and get_upper() == other.get_upper(); }
|
||||
#endif
|
||||
bool operator!=(const int128& other) const { return !(*this == other); }
|
||||
|
||||
int128 operator<<(const int& other) const;
|
||||
@@ -125,6 +129,8 @@ class gf2n_long
|
||||
|
||||
static int default_length() { return 128; }
|
||||
|
||||
static bool allows(Dtype type) { (void) type; return true; }
|
||||
|
||||
int128 get() const { return a; }
|
||||
__m128i to_m128i() const { return a.a; }
|
||||
word get_word() const { return _mm_cvtsi128_si64(a.a); }
|
||||
@@ -278,10 +284,15 @@ inline void mul128(__m128i a, __m128i b, __m128i *res1, __m128i *res2)
|
||||
{
|
||||
__m128i tmp3, tmp4, tmp5, tmp6;
|
||||
|
||||
#ifdef __PCLMUL__
|
||||
tmp3 = _mm_clmulepi64_si128(a, b, 0x00);
|
||||
tmp4 = _mm_clmulepi64_si128(a, b, 0x10);
|
||||
tmp5 = _mm_clmulepi64_si128(a, b, 0x01);
|
||||
tmp6 = _mm_clmulepi64_si128(a, b, 0x11);
|
||||
#else
|
||||
(void) a, (void) b;
|
||||
throw runtime_error("need to compile with PCLMUL support");
|
||||
#endif
|
||||
|
||||
tmp4 = _mm_xor_si128(tmp4, tmp5);
|
||||
tmp5 = _mm_slli_si128(tmp4, 8);
|
||||
|
||||
12
Math/gfp.cpp
12
Math/gfp.cpp
@@ -151,6 +151,18 @@ void gfp::reqbl(int n)
|
||||
}
|
||||
}
|
||||
|
||||
bool gfp::allows(Dtype type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case DATA_BITGF2NTRIPLE:
|
||||
case DATA_BITTRIPLE:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void to_signed_bigint(bigint& ans, const gfp& x)
|
||||
{
|
||||
to_bigint(ans, x);
|
||||
|
||||
@@ -47,7 +47,7 @@ class gfp
|
||||
static Zp_Data& get_ZpD()
|
||||
{ return ZpD; }
|
||||
|
||||
static DataFieldType field_type() { return DATA_MODP; }
|
||||
static DataFieldType field_type() { return DATA_INT; }
|
||||
static char type_char() { return 'p'; }
|
||||
static string type_string() { return "gfp"; }
|
||||
|
||||
@@ -55,6 +55,8 @@ class gfp
|
||||
|
||||
static void reqbl(int n);
|
||||
|
||||
static bool allows(Dtype type);
|
||||
|
||||
void assign(const gfp& g) { a=g.a; }
|
||||
void assign_zero() { assignZero(a,ZpD); }
|
||||
void assign_one() { assignOne(a,ZpD); }
|
||||
@@ -108,7 +110,7 @@ class gfp
|
||||
|
||||
|
||||
bool is_zero() const { return isZero(a,ZpD); }
|
||||
bool is_one() const { return isOne(a,ZpD); }
|
||||
bool is_one() const { return isOne(a,ZpD); }
|
||||
bool is_bit() const { return is_zero() or is_one(); }
|
||||
bool equal(const gfp& y) const { return areEqual(a,y.a,ZpD); }
|
||||
bool operator==(const gfp& y) const { return equal(y); }
|
||||
|
||||
@@ -192,6 +192,7 @@ inline void mpn_add_n_use_fixed(mp_limb_t* res, const mp_limb_t* x, const mp_lim
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __BMI2__
|
||||
template <int L, int M, bool ADD>
|
||||
inline void mpn_addmul_1_fixed__(mp_limb_t* res, const mp_limb_t* y, mp_limb_t x)
|
||||
{
|
||||
@@ -267,5 +268,6 @@ inline void mpn_mul_fixed(mp_limb_t* res, const mp_limb_t* x, const mp_limb_t* y
|
||||
{
|
||||
mpn_mul_fixed_<N + M, N, M>(res, x, y);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MATH_MPN_FIXED_H_ */
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
template <class T>
|
||||
T operator*(const bool& x, const T& y) { return x ? y : T(); }
|
||||
template <class T>
|
||||
T operator*(const T& y, const bool& x) { return x ? y : T(); }
|
||||
//template <class T>
|
||||
//T operator*(const T& y, const bool& x) { return x ? y : T(); }
|
||||
template <class T>
|
||||
T& operator*=(const T& y, const bool& x) { y = x ? y : T(); return y; }
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ CryptoPlayer::CryptoPlayer(const Names& Nms, int id_base) :
|
||||
|
||||
CryptoPlayer::~CryptoPlayer()
|
||||
{
|
||||
close_client_socket(plaintext_player.socket(my_num()));
|
||||
plaintext_player.sockets.clear();
|
||||
for (int i = 0; i < num_players(); i++)
|
||||
delete sockets[i];
|
||||
|
||||
@@ -188,10 +188,15 @@ template<>
|
||||
MultiPlayer<int>::~MultiPlayer()
|
||||
{
|
||||
/* Close down the sockets */
|
||||
for (int i=0; i<nplayers; i++)
|
||||
close_client_socket(sockets[i]);
|
||||
for (auto socket : sockets)
|
||||
close_client_socket(socket);
|
||||
close_client_socket(send_to_self_socket);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
MultiPlayer<T>::~MultiPlayer()
|
||||
{
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
@@ -336,6 +341,11 @@ void MultiPlayer<T>::exchange(int other, octetStream& o) const
|
||||
sent += o.get_length();
|
||||
}
|
||||
|
||||
void Player::exchange_relative(int offset, octetStream& o) const
|
||||
{
|
||||
exchange(get_player(offset), o);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void MultiPlayer<T>::pass_around(octetStream& o, int offset) const
|
||||
|
||||
@@ -169,6 +169,10 @@ public:
|
||||
void receive_relative(vector<octetStream>& o) const;
|
||||
void receive_relative(int offset, octetStream& o) const;
|
||||
|
||||
// exchange data with minimal memory usage
|
||||
void exchange(int other, octetStream& o) const = 0;
|
||||
void exchange_relative(int offset, octetStream& o) const;
|
||||
|
||||
/* Broadcast and Receive data to/from all players
|
||||
* - Assumes o[player_no] contains the thing broadcast by me
|
||||
*/
|
||||
@@ -204,7 +208,7 @@ public:
|
||||
// portnum bases in each thread
|
||||
MultiPlayer(const Names& Nms,int id_base=0);
|
||||
|
||||
virtual ~MultiPlayer() {}
|
||||
virtual ~MultiPlayer();
|
||||
|
||||
T socket(int i) const { return sockets[i]; }
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ void set_up_client_socket(int& mysocket,const char* hostname,int Portnum)
|
||||
|
||||
void close_client_socket(int socket)
|
||||
{
|
||||
if (close(socket) < 0 and errno != EBADF)
|
||||
if (close(socket))
|
||||
{
|
||||
char tmp[1000];
|
||||
sprintf(tmp, "close(%d)", socket);
|
||||
|
||||
@@ -56,16 +56,27 @@ int get_ack(int socket);
|
||||
|
||||
extern unsigned long long sent_amount, sent_counter;
|
||||
|
||||
|
||||
inline size_t send_non_blocking(int socket, octet* msg, size_t len)
|
||||
{
|
||||
int j = send(socket,msg,len,0);
|
||||
if (j < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{ error("Send error - 1 "); }
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void send(int socket,octet *msg,size_t len)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
int j = send(socket,msg+i,len-i,0);
|
||||
i += j;
|
||||
if (j < 0 and errno != EINTR)
|
||||
{ error("Send error - 1 "); }
|
||||
i += send_non_blocking(socket, msg + i, len - i);
|
||||
}
|
||||
|
||||
sent_amount += len;
|
||||
|
||||
@@ -14,12 +14,17 @@
|
||||
|
||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
|
||||
|
||||
inline size_t send_non_blocking(ssl_socket* socket, octet* data, size_t length)
|
||||
{
|
||||
return socket->write_some(boost::asio::buffer(data, length));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void send(ssl_socket* socket, octet* data, size_t length)
|
||||
{
|
||||
size_t sent = 0;
|
||||
while (sent < length)
|
||||
sent += socket->write_some(boost::asio::buffer(data + sent, length - sent));
|
||||
sent += send_non_blocking(socket, data + sent, length - sent);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -384,8 +384,7 @@ bool square128::operator==(square128& other)
|
||||
{
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
__m128i tmp = rows[i] ^ other.rows[i];
|
||||
if (not _mm_test_all_zeros(tmp, tmp))
|
||||
if (int128(rows[i]) != other.rows[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -137,7 +137,7 @@ class BitVector
|
||||
memcpy(bytes + offset, (octet*)&w, sizeof(word));
|
||||
}
|
||||
|
||||
int128 get_int128(int i) const { return _mm_lddqu_si128((__m128i*)bytes + i); }
|
||||
int128 get_int128(int i) const { return _mm_loadu_si128((__m128i*)bytes + i); }
|
||||
void set_int128(int i, int128 a) { *((__m128i*)bytes + i) = a.a; }
|
||||
|
||||
int get_bit(int i) const
|
||||
|
||||
@@ -143,6 +143,15 @@ int main(int argc, const char** argv)
|
||||
"-N", // Flag token.
|
||||
"--nparties" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
0, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Use encrypted channels.", // Help description.
|
||||
"-e", // Flag token.
|
||||
"--encrypted" // Flag token.
|
||||
);
|
||||
|
||||
opt.resetArgs();
|
||||
opt.parse(argc, argv);
|
||||
@@ -250,7 +259,8 @@ int main(int argc, const char** argv)
|
||||
{
|
||||
Machine<sgfp, Share<gf2n>>(playerno, playerNames, progname, memtype, lg2,
|
||||
opt.get("--direct")->isSet, opening_sum, opt.get("--parallel")->isSet,
|
||||
opt.get("--threads")->isSet, max_broadcast, false, false,
|
||||
opt.get("--threads")->isSet, max_broadcast,
|
||||
opt.get("--encrypted")->isSet, false,
|
||||
online_opts).run();
|
||||
|
||||
if (server)
|
||||
|
||||
94
Processor/BaseMachine.cpp
Normal file
94
Processor/BaseMachine.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* BaseMachine.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BaseMachine.h"
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
BaseMachine* BaseMachine::singleton = 0;
|
||||
|
||||
BaseMachine& BaseMachine::s()
|
||||
{
|
||||
if (singleton)
|
||||
return *singleton;
|
||||
else
|
||||
throw runtime_error("no singleton");
|
||||
}
|
||||
|
||||
BaseMachine::BaseMachine() : nthreads(0)
|
||||
{
|
||||
if (not singleton)
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
void BaseMachine::load_schedule(string progname)
|
||||
{
|
||||
this->progname = progname;
|
||||
string fname = "Programs/Schedules/" + progname + ".sch";
|
||||
cerr << "Opening file " << fname << endl;
|
||||
inpf.open(fname);
|
||||
if (inpf.fail()) { throw file_error("Missing '" + fname + "'. Did you compile '" + progname + "'?"); }
|
||||
|
||||
int nprogs;
|
||||
inpf >> nthreads;
|
||||
inpf >> nprogs;
|
||||
|
||||
cerr << "Number of threads I will run in parallel = " << nthreads << endl;
|
||||
cerr << "Number of program sequences I need to load = " << nprogs << endl;
|
||||
|
||||
// Load in the programs
|
||||
string threadname;
|
||||
for (int i=0; i<nprogs; i++)
|
||||
{ inpf >> threadname;
|
||||
string filename = "Programs/Bytecode/" + threadname + ".bc";
|
||||
cerr << "Loading program " << i << " from " << filename << endl;
|
||||
load_program(threadname, filename);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMachine::print_compiler()
|
||||
{
|
||||
|
||||
char compiler[1000];
|
||||
inpf.get();
|
||||
inpf.getline(compiler, 1000);
|
||||
if (compiler[0] != 0)
|
||||
cerr << "Compiler: " << compiler << endl;
|
||||
inpf.close();
|
||||
}
|
||||
|
||||
void BaseMachine::load_program(string threadname, string filename)
|
||||
{
|
||||
(void)threadname;
|
||||
(void)filename;
|
||||
throw not_implemented();
|
||||
}
|
||||
|
||||
void BaseMachine::time()
|
||||
{
|
||||
cout << "Elapsed time: " << timer[0].elapsed() << endl;
|
||||
}
|
||||
|
||||
void BaseMachine::start(int n)
|
||||
{
|
||||
cout << "Starting timer " << n << " at " << timer[n].elapsed()
|
||||
<< " after " << timer[n].idle() << endl;
|
||||
timer[n].start();
|
||||
}
|
||||
|
||||
void BaseMachine::stop(int n)
|
||||
{
|
||||
timer[n].stop();
|
||||
cout << "Stopped timer " << n << " at " << timer[n].elapsed() << endl;
|
||||
}
|
||||
|
||||
void BaseMachine::print_timers()
|
||||
{
|
||||
cerr << "Time = " << timer[0].elapsed() << " seconds " << endl;
|
||||
timer.erase(0);
|
||||
for (map<int,Timer>::iterator it = timer.begin(); it != timer.end(); it++)
|
||||
cerr << "Time" << it->first << " = " << it->second.elapsed() << " seconds " << endl;
|
||||
}
|
||||
@@ -7,22 +7,34 @@
|
||||
#define PROCESSOR_BEAVER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
using namespace std;
|
||||
|
||||
#include "Replicated.h"
|
||||
|
||||
template<class T> class SubProcessor;
|
||||
template<class T> class MAC_Check_Base;
|
||||
class Player;
|
||||
|
||||
template<class T>
|
||||
class Beaver
|
||||
class Beaver : public ProtocolBase<T>
|
||||
{
|
||||
vector<T> shares;
|
||||
vector<typename T::clear> opened;
|
||||
vector<array<T, 3>> triples;
|
||||
typename vector<typename T::clear>::iterator it;
|
||||
typename vector<array<T, 3>>::iterator triple;
|
||||
SubProcessor<T>* proc;
|
||||
|
||||
public:
|
||||
Player& P;
|
||||
|
||||
static void muls(const vector<int>& reg, SubProcessor<T>& proc,
|
||||
MAC_Check_Base<T>& MC, int size);
|
||||
Beaver(Player& P) : proc(0), P(P) {}
|
||||
|
||||
Beaver(Player& P) : P(P) {}
|
||||
void init_mul(SubProcessor<T>* proc);
|
||||
typename T::clear prepare_mul(const T& x, const T& y);
|
||||
void exchange();
|
||||
T finalize_mul();
|
||||
};
|
||||
|
||||
#endif /* PROCESSOR_BEAVER_H_ */
|
||||
|
||||
@@ -7,44 +7,46 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
|
||||
template<class T>
|
||||
void Beaver<T>::muls(const vector<int>& reg, SubProcessor<T>& proc, MAC_Check_Base<T>& MC,
|
||||
int size)
|
||||
void Beaver<T>::init_mul(SubProcessor<T>* proc)
|
||||
{
|
||||
assert(reg.size() % 3 == 0);
|
||||
int n = reg.size() / 3;
|
||||
vector<T>& shares = proc.Sh_PO;
|
||||
vector<typename T::clear>& opened = proc.PO;
|
||||
this->proc = proc;
|
||||
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++;
|
||||
}
|
||||
opened.clear();
|
||||
triples.clear();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename T::clear Beaver<T>::prepare_mul(const T& x, const T& y)
|
||||
{
|
||||
triples.push_back({{}});
|
||||
auto& triple = triples.back();
|
||||
proc->DataF.get(DATA_TRIPLE, triple.data());
|
||||
shares.push_back(x - triple[0]);
|
||||
shares.push_back(y - triple[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Beaver<T>::exchange()
|
||||
{
|
||||
proc->MC.POpen(opened, shares, P);
|
||||
it = opened.begin();
|
||||
triple = triples.begin();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T Beaver<T>::finalize_mul()
|
||||
{
|
||||
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], P.my_num(), proc->MC.get_alphai());
|
||||
triple++;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "Math/gf2n.h"
|
||||
#include "Math/Share.h"
|
||||
#include "Math/field_types.h"
|
||||
#include "Processor/Buffer.h"
|
||||
#include "Tools/Buffer.h"
|
||||
#include "Processor/InputTuple.h"
|
||||
#include "Tools/Lock.h"
|
||||
#include "Networking/Player.h"
|
||||
@@ -18,8 +18,6 @@
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
enum Dtype { DATA_TRIPLE, DATA_SQUARE, DATA_BIT, DATA_INVERSE, DATA_BITTRIPLE, DATA_BITGF2NTRIPLE, N_DTYPE };
|
||||
|
||||
class DataTag
|
||||
{
|
||||
int t[4];
|
||||
@@ -95,8 +93,6 @@ 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;
|
||||
static Lock tuple_lengths_lock;
|
||||
|
||||
|
||||
@@ -9,77 +9,17 @@
|
||||
#include "Math/MaliciousShamirShare.h"
|
||||
|
||||
#include "Processor/MaliciousRepPrep.hpp"
|
||||
#include "Processor/Replicated.hpp"
|
||||
//#include "Processor/Replicated.hpp"
|
||||
#include "Processor/ReplicatedPrep.hpp"
|
||||
#include "Processor/Input.hpp"
|
||||
#include "Processor/ReplicatedInput.hpp"
|
||||
#include "Processor/Shamir.hpp"
|
||||
#include "Auth/MaliciousShamirMC.hpp"
|
||||
//#include "Processor/Input.hpp"
|
||||
//#include "Processor/ReplicatedInput.hpp"
|
||||
//#include "Processor/Shamir.hpp"
|
||||
//#include "Auth/MaliciousShamirMC.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
|
||||
const char* DataPositions::field_names[] = { "gfp", "gf2n", "bit", "int64" };
|
||||
|
||||
template<>
|
||||
const bool Sub_Data_Files<sgfp>::implemented[N_DTYPE] =
|
||||
{ true, true, true, true, false, false }
|
||||
;
|
||||
|
||||
template<>
|
||||
const bool Sub_Data_Files<Share<gf2n>>::implemented[N_DTYPE] =
|
||||
{ true, true, true, true, true, true }
|
||||
;
|
||||
|
||||
template<>
|
||||
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 }
|
||||
;
|
||||
|
||||
template<>
|
||||
const bool Sub_Data_Files<ShamirShare<gfp>>::implemented[N_DTYPE] =
|
||||
{ false, false, false, false, false, false }
|
||||
;
|
||||
|
||||
template<>
|
||||
const bool Sub_Data_Files<ShamirShare<gf2n>>::implemented[N_DTYPE] =
|
||||
{ false, false, false, false, false, false }
|
||||
;
|
||||
|
||||
template<>
|
||||
const bool Sub_Data_Files<MaliciousShamirShare<gfp>>::implemented[N_DTYPE] =
|
||||
{ false, false, false, false, false, false }
|
||||
;
|
||||
|
||||
template<>
|
||||
const bool Sub_Data_Files<MaliciousShamirShare<gf2n>>::implemented[N_DTYPE] =
|
||||
{ false, false, false, false, false, false }
|
||||
;
|
||||
const char* DataPositions::field_names[] = { "int", "gf2n", "bit" };
|
||||
|
||||
const int DataPositions::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 };
|
||||
|
||||
@@ -88,73 +28,6 @@ Lock Sub_Data_Files<T>::tuple_lengths_lock;
|
||||
template<class T>
|
||||
map<DataTag, int> Sub_Data_Files<T>::tuple_lengths;
|
||||
|
||||
template<>
|
||||
Preprocessing<Rep3Share<gfp>>* Preprocessing<Rep3Share<gfp>>::get_live_prep(
|
||||
SubProcessor<Rep3Share<gfp>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<Rep3Share<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<Rep3Share<gf2n>>* Preprocessing<Rep3Share<gf2n>>::get_live_prep(
|
||||
SubProcessor<Rep3Share<gf2n>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<Rep3Share<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<Rep3Share<Integer>>* Preprocessing<Rep3Share<Integer>>::get_live_prep(
|
||||
SubProcessor<Rep3Share<Integer>>* proc)
|
||||
{
|
||||
return new ReplicatedRingPrep<Rep3Share<Integer>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousRep3Share<gfp>>* Preprocessing<MaliciousRep3Share<gfp>>::get_live_prep(
|
||||
SubProcessor<MaliciousRep3Share<gfp>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousRep3Share<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousRep3Share<gf2n>>* Preprocessing<MaliciousRep3Share<gf2n>>::get_live_prep(
|
||||
SubProcessor<MaliciousRep3Share<gf2n>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousRep3Share<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<ShamirShare<gfp>>* Preprocessing<ShamirShare<gfp>>::get_live_prep(
|
||||
SubProcessor<ShamirShare<gfp>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<ShamirShare<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<ShamirShare<gf2n>>* Preprocessing<ShamirShare<gf2n>>::get_live_prep(
|
||||
SubProcessor<ShamirShare<gf2n>>* proc)
|
||||
{
|
||||
return new ReplicatedPrep<ShamirShare<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousShamirShare<gfp>>* Preprocessing<MaliciousShamirShare<gfp>>::get_live_prep(
|
||||
SubProcessor<MaliciousShamirShare<gfp>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousShamirShare<gfp>>(proc);
|
||||
}
|
||||
|
||||
template<>
|
||||
Preprocessing<MaliciousShamirShare<gf2n>>* Preprocessing<MaliciousShamirShare<gf2n>>::get_live_prep(
|
||||
SubProcessor<MaliciousShamirShare<gf2n>>* proc)
|
||||
{
|
||||
(void) proc;
|
||||
return new MaliciousRepPrep<MaliciousShamirShare<gf2n>>(proc);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Preprocessing<T>* Preprocessing<T>::get_live_prep(SubProcessor<T>* proc)
|
||||
{
|
||||
@@ -270,7 +143,7 @@ Sub_Data_Files<T>::Sub_Data_Files(int my_num, int num_players,
|
||||
string suffix = get_suffix(thread_num);
|
||||
for (int dtype = 0; dtype < N_DTYPE; dtype++)
|
||||
{
|
||||
if (implemented[dtype])
|
||||
if (T::clear::allows(Dtype(dtype)))
|
||||
{
|
||||
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());
|
||||
@@ -329,7 +202,7 @@ void Sub_Data_Files<T>::seekg(DataPositions& pos)
|
||||
{
|
||||
DataFieldType field_type = T::field_type();
|
||||
for (int dtype = 0; dtype < N_DTYPE; dtype++)
|
||||
if (implemented[dtype])
|
||||
if (T::clear::allows(Dtype(dtype)))
|
||||
buffers[dtype].seekg(pos.files[field_type][dtype]);
|
||||
for (int j = 0; j < num_players; j++)
|
||||
if (j == my_num)
|
||||
@@ -437,19 +310,3 @@ void Sub_Data_Files<T>::get(vector<T>& S, DataTag tag, const vector<int>& regs,
|
||||
for (unsigned int i = 0; i < regs.size(); i++)
|
||||
extended[tag].input(S[regs[i] + j]);
|
||||
}
|
||||
|
||||
template class Sub_Data_Files<Share<gf2n>>;
|
||||
template class Sub_Data_Files<sgfp>;
|
||||
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, 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>>;
|
||||
template class Data_Files<ShamirShare<gfp>, ShamirShare<gf2n>>;
|
||||
template class Data_Files<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>;
|
||||
@@ -10,7 +10,7 @@
|
||||
using namespace std;
|
||||
|
||||
#include "Math/Share.h"
|
||||
#include "Processor/Buffer.h"
|
||||
#include "Tools/Buffer.h"
|
||||
#include "Tools/time-func.h"
|
||||
|
||||
class ArithmeticProcessor;
|
||||
|
||||
@@ -92,6 +92,8 @@ enum
|
||||
// Open
|
||||
OPEN = 0xA5,
|
||||
MULS = 0xA6,
|
||||
MULRS = 0xA7,
|
||||
DOTPRODS = 0xA8,
|
||||
// Data access
|
||||
TRIPLE = 0x50,
|
||||
BIT = 0x51,
|
||||
@@ -214,6 +216,8 @@ enum
|
||||
// Open
|
||||
GOPEN = 0x1A5,
|
||||
GMULS = 0x1A6,
|
||||
GMULRS = 0x1A7,
|
||||
GDOTPRODS = 0x1A8,
|
||||
// Data access
|
||||
GTRIPLE = 0x150,
|
||||
GBIT = 0x151,
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
#include "Auth/ShamirMC.h"
|
||||
#include "Math/MaliciousShamirShare.h"
|
||||
|
||||
#include "Processor/Processor.hpp"
|
||||
//#include "Processor/Processor.hpp"
|
||||
#include "Processor/Binary_File_IO.hpp"
|
||||
#include "Processor/Input.hpp"
|
||||
#include "Processor/Beaver.hpp"
|
||||
#include "Processor/Shamir.hpp"
|
||||
#include "Processor/ShamirInput.hpp"
|
||||
#include "Processor/Replicated.hpp"
|
||||
#include "Auth/MaliciousRepMC.hpp"
|
||||
#include "Auth/ShamirMC.hpp"
|
||||
//#include "Processor/Input.hpp"
|
||||
//#include "Processor/Beaver.hpp"
|
||||
//#include "Processor/Shamir.hpp"
|
||||
//#include "Processor/ShamirInput.hpp"
|
||||
//#include "Processor/Replicated.hpp"
|
||||
//#include "Auth/MaliciousRepMC.hpp"
|
||||
//#include "Auth/ShamirMC.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
@@ -33,6 +33,7 @@
|
||||
#undef DEBUG
|
||||
|
||||
// Convert modp to signed bigint of a given bit length
|
||||
inline
|
||||
void to_signed_bigint(bigint& bi, const gfp& x, int len)
|
||||
{
|
||||
to_bigint(bi, x);
|
||||
@@ -53,7 +54,7 @@ void to_signed_bigint(bigint& bi, const gfp& x, int len)
|
||||
bi = -bi;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void Instruction::parse(istream& s)
|
||||
{
|
||||
n=0; start.resize(0);
|
||||
@@ -70,7 +71,7 @@ void Instruction::parse(istream& s)
|
||||
parse_operands(s, pos);
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void BaseInstruction::parse_operands(istream& s, int pos)
|
||||
{
|
||||
int num_var_args = 0;
|
||||
@@ -277,7 +278,7 @@ void BaseInstruction::parse_operands(istream& s, int pos)
|
||||
case CRASH:
|
||||
case STARTGRIND:
|
||||
case STOPGRIND:
|
||||
break;
|
||||
break;
|
||||
// instructions with 4 register operands
|
||||
case PRINTFLOATPLAIN:
|
||||
get_vector(4, start, s);
|
||||
@@ -288,6 +289,10 @@ void BaseInstruction::parse_operands(istream& s, int pos)
|
||||
case GOPEN:
|
||||
case MULS:
|
||||
case GMULS:
|
||||
case MULRS:
|
||||
case GMULRS:
|
||||
case DOTPRODS:
|
||||
case GDOTPRODS:
|
||||
case INPUT:
|
||||
case GINPUT:
|
||||
num_var_args = get_int(s);
|
||||
@@ -385,7 +390,7 @@ void BaseInstruction::parse_operands(istream& s, int pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool Instruction::get_offline_data_usage(DataPositions& usage)
|
||||
{
|
||||
switch (opcode)
|
||||
@@ -415,6 +420,7 @@ bool Instruction::get_offline_data_usage(DataPositions& usage)
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
int BaseInstruction::get_reg_type() const
|
||||
{
|
||||
switch (opcode) {
|
||||
@@ -451,10 +457,27 @@ int BaseInstruction::get_reg_type() const
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned BaseInstruction::get_max_reg(int reg_type) const
|
||||
{
|
||||
if (get_reg_type() != reg_type) { return 0; }
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case DOTPRODS:
|
||||
{
|
||||
int res = 0;
|
||||
auto it = start.begin();
|
||||
while (it != start.end())
|
||||
{
|
||||
int n = *it;
|
||||
res = max(res, *it++);
|
||||
it += n - 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
const int *begin, *end;
|
||||
if (start.size())
|
||||
{
|
||||
@@ -473,6 +496,7 @@ unsigned BaseInstruction::get_max_reg(int reg_type) const
|
||||
return res + size;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned Instruction::get_mem(RegType reg_type, SecrecyType sec_type) const
|
||||
{
|
||||
if (get_reg_type() == reg_type and is_direct_memory_access(sec_type))
|
||||
@@ -481,6 +505,7 @@ unsigned Instruction::get_mem(RegType reg_type, SecrecyType sec_type) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline
|
||||
bool BaseInstruction::is_direct_memory_access(SecrecyType sec_type) const
|
||||
{
|
||||
if (sec_type == SECRET)
|
||||
@@ -514,7 +539,7 @@ bool BaseInstruction::is_direct_memory_access(SecrecyType sec_type) const
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline
|
||||
ostream& operator<<(ostream& s,const Instruction& instr)
|
||||
{
|
||||
s << instr.opcode << " : ";
|
||||
@@ -1386,6 +1411,18 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
case GMULS:
|
||||
Proc.Proc2.protocol.muls(start, Proc.Proc2, Proc.MC2, size);
|
||||
return;
|
||||
case MULRS:
|
||||
Proc.Procp.protocol.mulrs(start, Proc.Procp);
|
||||
return;
|
||||
case GMULRS:
|
||||
Proc.Proc2.protocol.mulrs(start, Proc.Proc2);
|
||||
return;
|
||||
case DOTPRODS:
|
||||
Proc.Procp.protocol.dotprods(start, Proc.Procp);
|
||||
return;
|
||||
case GDOTPRODS:
|
||||
Proc.Proc2.protocol.dotprods(start, Proc.Proc2);
|
||||
return;
|
||||
case JMP:
|
||||
Proc.PC += (signed int) n;
|
||||
break;
|
||||
@@ -1701,10 +1738,3 @@ void Program::execute(Processor<sint, sgf2n>& Proc) const
|
||||
while (Proc.PC<size)
|
||||
{ p[Proc.PC].execute(Proc); }
|
||||
}
|
||||
|
||||
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;
|
||||
template void Program::execute(Processor<ShamirShare<gfp>, ShamirShare<gf2n>>& Proc) const;
|
||||
template void Program::execute(Processor<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>& Proc) const;
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
using namespace std;
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
@@ -71,6 +72,8 @@ class Machine : public BaseMachine
|
||||
|
||||
OnlineOptions opts;
|
||||
|
||||
atomic<size_t> data_sent;
|
||||
|
||||
Machine(int my_number, Names& playerNames, string progname,
|
||||
string memtype, int lg2, bool direct, int opening_sum, bool parallel,
|
||||
bool receive_threads, int max_broadcast, bool use_encryption, bool live_prep,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "ShamirInput.hpp"
|
||||
#include "Shamir.hpp"
|
||||
#include "Replicated.hpp"
|
||||
#include "Beaver.hpp"
|
||||
#include "Auth/ShamirMC.hpp"
|
||||
#include "Auth/MaliciousShamirMC.hpp"
|
||||
|
||||
@@ -24,24 +25,6 @@
|
||||
#include <pthread.h>
|
||||
using namespace std;
|
||||
|
||||
BaseMachine* BaseMachine::singleton = 0;
|
||||
|
||||
BaseMachine& BaseMachine::s()
|
||||
{
|
||||
if (singleton)
|
||||
return *singleton;
|
||||
else
|
||||
throw runtime_error("no singleton");
|
||||
}
|
||||
|
||||
BaseMachine::BaseMachine() : nthreads(0)
|
||||
{
|
||||
if (singleton)
|
||||
throw runtime_error("there can only be one");
|
||||
else
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
string progname_str, string memtype, int lg2, bool direct,
|
||||
@@ -50,7 +33,8 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
: 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), live_prep(live_prep), opts(opts)
|
||||
use_encryption(use_encryption), live_prep(live_prep), opts(opts),
|
||||
data_sent(0)
|
||||
{
|
||||
if (opening_sum < 2)
|
||||
this->opening_sum = N.num_players();
|
||||
@@ -166,42 +150,6 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMachine::load_schedule(string progname)
|
||||
{
|
||||
this->progname = progname;
|
||||
string fname = "Programs/Schedules/" + progname + ".sch";
|
||||
cerr << "Opening file " << fname << endl;
|
||||
inpf.open(fname);
|
||||
if (inpf.fail()) { throw file_error("Missing '" + fname + "'. Did you compile '" + progname + "'?"); }
|
||||
|
||||
int nprogs;
|
||||
inpf >> nthreads;
|
||||
inpf >> nprogs;
|
||||
|
||||
cerr << "Number of threads I will run in parallel = " << nthreads << endl;
|
||||
cerr << "Number of program sequences I need to load = " << nprogs << endl;
|
||||
|
||||
// Load in the programs
|
||||
string threadname;
|
||||
for (int i=0; i<nprogs; i++)
|
||||
{ inpf >> threadname;
|
||||
string filename = "Programs/Bytecode/" + threadname + ".bc";
|
||||
cerr << "Loading program " << i << " from " << filename << endl;
|
||||
load_program(threadname, filename);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseMachine::print_compiler()
|
||||
{
|
||||
|
||||
char compiler[1000];
|
||||
inpf.get();
|
||||
inpf.getline(compiler, 1000);
|
||||
if (compiler[0] != 0)
|
||||
cerr << "Compiler: " << compiler << endl;
|
||||
inpf.close();
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
void Machine<sint, sgf2n>::load_program(string threadname, string filename)
|
||||
{
|
||||
@@ -345,6 +293,7 @@ void Machine<sint, sgf2n>::run()
|
||||
cerr << "Finish timer: " << finish_timer.elapsed() << endl;
|
||||
cerr << "Process timer: " << proc_timer.elapsed() << endl;
|
||||
print_timers();
|
||||
cerr << "Data sent = " << data_sent / 1e6 << " MB" << endl;
|
||||
|
||||
if (opening_sum < N.num_players() && !direct)
|
||||
cerr << "Summed at most " << opening_sum << " shares at once with indirect communication" << endl;
|
||||
@@ -368,12 +317,6 @@ void Machine<sint, sgf2n>::run()
|
||||
outf << M2 << Mp << Mi;
|
||||
outf.close();
|
||||
|
||||
extern unsigned long long sent_amount, sent_counter;
|
||||
cerr << "Data sent = " << sent_amount << " bytes in "
|
||||
<< sent_counter << " calls,";
|
||||
cerr << sent_amount / sent_counter / N.num_players()
|
||||
<< " bytes per call" << endl;
|
||||
|
||||
for (int dtype = 0; dtype < N_DTYPE; dtype++)
|
||||
{
|
||||
cerr << "Num " << DataPositions::dtype_names[dtype] << "\t=";
|
||||
@@ -407,48 +350,8 @@ 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;
|
||||
(void)filename;
|
||||
throw not_implemented();
|
||||
}
|
||||
|
||||
void BaseMachine::time()
|
||||
{
|
||||
cout << "Elapsed time: " << timer[0].elapsed() << endl;
|
||||
}
|
||||
|
||||
void BaseMachine::start(int n)
|
||||
{
|
||||
cout << "Starting timer " << n << " at " << timer[n].elapsed()
|
||||
<< " after " << timer[n].idle() << endl;
|
||||
timer[n].start();
|
||||
}
|
||||
|
||||
void BaseMachine::stop(int n)
|
||||
{
|
||||
timer[n].stop();
|
||||
cout << "Stopped timer " << n << " at " << timer[n].elapsed() << endl;
|
||||
}
|
||||
|
||||
void BaseMachine::print_timers()
|
||||
{
|
||||
cerr << "Time = " << timer[0].elapsed() << " seconds " << endl;
|
||||
timer.erase(0);
|
||||
for (map<int,Timer>::iterator it = timer.begin(); it != timer.end(); it++)
|
||||
cerr << "Time" << it->first << " = " << it->second.elapsed() << " seconds " << endl;
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
void Machine<sint, sgf2n>::reqbl(int n)
|
||||
{
|
||||
sint::clear::reqbl(n);
|
||||
}
|
||||
|
||||
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>>;
|
||||
template class Machine<ShamirShare<gfp>, ShamirShare<gf2n>>;
|
||||
template class Machine<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>;
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "MaliciousRepPrep.h"
|
||||
#include "Auth/Subroutines.h"
|
||||
#include "Auth/MaliciousRepMC.hpp"
|
||||
//#include "Auth/MaliciousRepMC.hpp"
|
||||
|
||||
template<class T>
|
||||
MaliciousRepPrep<T>::MaliciousRepPrep(SubProcessor<T>* proc) :
|
||||
@@ -41,7 +41,7 @@ template<class T>
|
||||
void MaliciousRepPrep<T>::buffer_triples()
|
||||
{
|
||||
auto& triples = this->triples;
|
||||
auto& buffer_size = this->buffer_size;
|
||||
auto buffer_size = this->buffer_size;
|
||||
clear_tmp();
|
||||
Player& P = honest_prep.protocol->P;
|
||||
triples.clear();
|
||||
@@ -51,8 +51,8 @@ void MaliciousRepPrep<T>::buffer_triples()
|
||||
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});
|
||||
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++)
|
||||
@@ -86,7 +86,7 @@ template<class T>
|
||||
void MaliciousRepPrep<T>::buffer_squares()
|
||||
{
|
||||
auto& squares = this->squares;
|
||||
auto& buffer_size = this->buffer_size;
|
||||
auto buffer_size = this->buffer_size;
|
||||
clear_tmp();
|
||||
Player& P = honest_prep.protocol->P;
|
||||
squares.clear();
|
||||
@@ -96,8 +96,8 @@ void MaliciousRepPrep<T>::buffer_squares()
|
||||
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});
|
||||
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++)
|
||||
@@ -132,7 +132,7 @@ template<class T>
|
||||
void MaliciousRepPrep<T>::buffer_bits()
|
||||
{
|
||||
auto& bits = this->bits;
|
||||
auto& buffer_size = this->buffer_size;
|
||||
auto buffer_size = this->buffer_size;
|
||||
clear_tmp();
|
||||
Player& P = honest_prep.protocol->P;
|
||||
bits.clear();
|
||||
@@ -142,7 +142,7 @@ void MaliciousRepPrep<T>::buffer_bits()
|
||||
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});
|
||||
check_squares.push_back({{f, h}});
|
||||
}
|
||||
auto t = Create_Random<typename T::clear>(P);
|
||||
for (int i = 0; i < buffer_size; i++)
|
||||
|
||||
@@ -170,6 +170,8 @@ void* Sub_Main_Func(void* ptr)
|
||||
cerr << "Thread " << num << " timer: " << thread_timer.elapsed() << endl;
|
||||
cerr << "Thread " << num << " wait timer: " << wait_timer.elapsed() << endl;
|
||||
|
||||
machine.data_sent += P.sent;
|
||||
|
||||
delete MC2;
|
||||
delete MCp;
|
||||
delete player;
|
||||
|
||||
@@ -41,7 +41,7 @@ class SubProcessor
|
||||
|
||||
template<class sint, class sgf2n> friend class Processor;
|
||||
template<class U> friend class SPDZ;
|
||||
template<class U> friend class PrepLessProtocol;
|
||||
template<class U> friend class ProtocolBase;
|
||||
template<class U> friend class Beaver;
|
||||
|
||||
public:
|
||||
@@ -61,7 +61,9 @@ public:
|
||||
void POpen_Stop(const vector<int>& reg,const Player& P,int size);
|
||||
void POpen(const vector<int>& reg,const Player& P,int size);
|
||||
|
||||
void muls(const vector<int>& reg,const Player& P,int size);
|
||||
void muls(const vector<int>& reg, int size);
|
||||
void mulrs(const vector<int>& reg);
|
||||
void dotprods(const vector<int>& reg);
|
||||
|
||||
vector<T>& get_S()
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ Processor<sint, sgf2n>::Processor(int thread_num,Player& P,
|
||||
template<class sint, class sgf2n>
|
||||
Processor<sint, sgf2n>::~Processor()
|
||||
{
|
||||
cerr << "Sent " << sent << " elements in " << rounds << " rounds" << endl;
|
||||
cerr << "Opened " << sent << " elements in " << rounds << " rounds" << endl;
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
@@ -485,6 +485,85 @@ void SubProcessor<T>::POpen(const vector<int>& reg, const Player& P,
|
||||
POpen_Stop(dest, P, size);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SubProcessor<T>::muls(const vector<int>& reg, int size)
|
||||
{
|
||||
assert(reg.size() % 3 == 0);
|
||||
int n = reg.size() / 3;
|
||||
|
||||
SubProcessor<T>& proc = *this;
|
||||
protocol.init_mul(&proc);
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
auto& x = proc.S[reg[3 * i + 1] + j];
|
||||
auto& y = proc.S[reg[3 * i + 2] + j];
|
||||
protocol.prepare_mul(x, y);
|
||||
}
|
||||
protocol.exchange();
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
proc.S[reg[3 * i] + j] = protocol.finalize_mul();
|
||||
}
|
||||
|
||||
protocol.counter += n * size;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SubProcessor<T>::mulrs(const vector<int>& reg)
|
||||
{
|
||||
assert(reg.size() % 4 == 0);
|
||||
int n = reg.size() / 4;
|
||||
|
||||
SubProcessor<T>& proc = *this;
|
||||
protocol.init_mul(&proc);
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < reg[4 * i]; j++)
|
||||
{
|
||||
auto& x = proc.S[reg[4 * i + 2] + j];
|
||||
auto& y = proc.S[reg[4 * i + 3]];
|
||||
protocol.prepare_mul(x, y);
|
||||
}
|
||||
protocol.exchange();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
for (int j = 0; j < reg[4 * i]; j++)
|
||||
{
|
||||
proc.S[reg[4 * i + 1] + j] = protocol.finalize_mul();
|
||||
}
|
||||
protocol.counter += reg[4 * i];
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SubProcessor<T>::dotprods(const vector<int>& reg)
|
||||
{
|
||||
protocol.init_dotprod(this);
|
||||
auto it = reg.begin();
|
||||
while (it != reg.end())
|
||||
{
|
||||
auto next = it + *it;
|
||||
it += 2;
|
||||
while (it != next)
|
||||
{
|
||||
protocol.prepare_dotprod(S[*it], S[*(it + 1)]);
|
||||
it += 2;
|
||||
}
|
||||
protocol.next_dotprod();
|
||||
}
|
||||
protocol.exchange();
|
||||
it = reg.begin();
|
||||
while (it != reg.end())
|
||||
{
|
||||
auto next = it + *it;
|
||||
it++;
|
||||
T& dest = S[*it];
|
||||
dest = protocol.finalize_dotprod((next - it) / 2);
|
||||
it = next;
|
||||
}
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
ostream& operator<<(ostream& s,const Processor<sint, sgf2n>& P)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "Processor/Data_Files.h"
|
||||
#include "Processor/Processor.h"
|
||||
|
||||
#include "Processor/Instruction.hpp"
|
||||
|
||||
void Program::compute_constants()
|
||||
{
|
||||
for (int reg_type = 0; reg_type < MAX_REG_TYPE; reg_type++)
|
||||
|
||||
@@ -30,33 +30,42 @@ public:
|
||||
Player& P;
|
||||
|
||||
ReplicatedBase(Player& P);
|
||||
|
||||
int get_n_relevant_players() { return P.num_players() - 1; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class PrepLessProtocol
|
||||
class ProtocolBase
|
||||
{
|
||||
public:
|
||||
int counter;
|
||||
|
||||
public:
|
||||
PrepLessProtocol();
|
||||
virtual ~PrepLessProtocol();
|
||||
ProtocolBase();
|
||||
virtual ~ProtocolBase();
|
||||
|
||||
void muls(const vector<int>& reg, SubProcessor<T>& proc, MAC_Check_Base<T>& MC,
|
||||
int size);
|
||||
void mulrs(const vector<int>& reg, SubProcessor<T>& proc);
|
||||
void dotprods(const vector<int>& reg, SubProcessor<T>& proc);
|
||||
|
||||
virtual void init_mul(SubProcessor<T>* proc) = 0;
|
||||
virtual typename T::clear prepare_mul(const T& x, const T& y) = 0;
|
||||
virtual void exchange() = 0;
|
||||
virtual T finalize_mul() = 0;
|
||||
|
||||
virtual T get_random() = 0;
|
||||
void init_dotprod(SubProcessor<T>* proc) { init_mul(proc); }
|
||||
void prepare_dotprod(const T& x, const T& y) { prepare_mul(x, y); }
|
||||
void next_dotprod() {}
|
||||
T finalize_dotprod(int length);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Replicated : public ReplicatedBase, public PrepLessProtocol<T>
|
||||
class Replicated : public ReplicatedBase, public ProtocolBase<T>
|
||||
{
|
||||
vector<octetStream> os;
|
||||
deque<typename T::clear> add_shares;
|
||||
typename T::clear dotprod_share;
|
||||
|
||||
public:
|
||||
typedef ReplicatedMC<T> MAC_Check;
|
||||
typedef ReplicatedInput<T> Input;
|
||||
@@ -78,6 +87,13 @@ public:
|
||||
void exchange();
|
||||
T finalize_mul();
|
||||
|
||||
void prepare_reshare(const typename T::clear& share);
|
||||
|
||||
void init_dotprod(SubProcessor<T>* proc);
|
||||
void prepare_dotprod(const T& x, const T& y);
|
||||
void next_dotprod();
|
||||
T finalize_dotprod(int length);
|
||||
|
||||
T get_random();
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "GC/ReplicatedSecret.h"
|
||||
|
||||
template<class T>
|
||||
PrepLessProtocol<T>::PrepLessProtocol() : counter(0)
|
||||
ProtocolBase<T>::ProtocolBase() : counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -38,36 +38,42 @@ inline ReplicatedBase::ReplicatedBase(Player& P) : P(P)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
PrepLessProtocol<T>::~PrepLessProtocol()
|
||||
ProtocolBase<T>::~ProtocolBase()
|
||||
{
|
||||
if (counter)
|
||||
cerr << "Number of multiplications: " << counter << endl;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PrepLessProtocol<T>::muls(const vector<int>& reg,
|
||||
void ProtocolBase<T>::muls(const vector<int>& reg,
|
||||
SubProcessor<T>& proc, MAC_Check_Base<T>& MC, int size)
|
||||
{
|
||||
(void)MC;
|
||||
assert(reg.size() % 3 == 0);
|
||||
int n = reg.size() / 3;
|
||||
proc.muls(reg, size);
|
||||
}
|
||||
|
||||
init_mul(&proc);
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
auto& x = proc.S[reg[3 * i + 1] + j];
|
||||
auto& y = proc.S[reg[3 * i + 2] + j];
|
||||
prepare_mul(x, y);
|
||||
}
|
||||
exchange();
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
proc.S[reg[3 * i] + j] = finalize_mul();
|
||||
}
|
||||
template<class T>
|
||||
void ProtocolBase<T>::mulrs(const vector<int>& reg,
|
||||
SubProcessor<T>& proc)
|
||||
{
|
||||
proc.mulrs(reg);
|
||||
}
|
||||
|
||||
counter += n * size;
|
||||
template<class T>
|
||||
void ProtocolBase<T>::dotprods(const vector<int>& reg,
|
||||
SubProcessor<T>& proc)
|
||||
{
|
||||
proc.dotprods(reg);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ProtocolBase<T>::finalize_dotprod(int length)
|
||||
{
|
||||
counter += length;
|
||||
T res;
|
||||
for (int i = 0; i < length; i++)
|
||||
res += finalize_mul();
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -87,28 +93,34 @@ void Replicated<T>::init_mul()
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename T::clear Replicated<T>::prepare_mul(const T& x,
|
||||
inline typename T::clear Replicated<T>::prepare_mul(const T& x,
|
||||
const T& y)
|
||||
{
|
||||
typename T::value_type add_share = x[0] * y.sum() + x[1] * y[0];
|
||||
typename T::value_type add_share = x.local_mul(y);
|
||||
prepare_reshare(add_share);
|
||||
return add_share;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Replicated<T>::prepare_reshare(const typename T::clear& share)
|
||||
{
|
||||
auto add_share = share;
|
||||
typename T::value_type tmp[2];
|
||||
for (int i = 0; i < 2; i++)
|
||||
tmp[i].randomize(shared_prngs[i]);
|
||||
add_share += tmp[0] - tmp[1];
|
||||
add_share.pack(os[0]);
|
||||
add_shares.push_back(add_share);
|
||||
return add_share;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Replicated<T>::exchange()
|
||||
{
|
||||
P.send_relative(1, os[0]);
|
||||
P.receive_relative(- 1, os[0]);
|
||||
P.pass_around(os[0], 1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T Replicated<T>::finalize_mul()
|
||||
inline T Replicated<T>::finalize_mul()
|
||||
{
|
||||
T result;
|
||||
result[0] = add_shares.front();
|
||||
@@ -117,6 +129,34 @@ T Replicated<T>::finalize_mul()
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Replicated<T>::init_dotprod(SubProcessor<T>* proc)
|
||||
{
|
||||
init_mul(proc);
|
||||
dotprod_share.assign_zero();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Replicated<T>::prepare_dotprod(const T& x, const T& y)
|
||||
{
|
||||
dotprod_share += x.local_mul(y);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Replicated<T>::next_dotprod()
|
||||
{
|
||||
prepare_reshare(dotprod_share);
|
||||
dotprod_share.assign_zero();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T Replicated<T>::finalize_dotprod(int length)
|
||||
{
|
||||
(void) length;
|
||||
this->counter++;
|
||||
return finalize_mul();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T Replicated<T>::get_random()
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ void ReplicatedInput<T>::reset(int player)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ReplicatedInput<T>::add_mine(const typename T::clear& input)
|
||||
inline void ReplicatedInput<T>::add_mine(const typename T::clear& input)
|
||||
{
|
||||
auto& shares = this->shares;
|
||||
shares.push_back({});
|
||||
@@ -89,7 +89,7 @@ void PrepLessInput<T>::stop(int player, vector<int> targets)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ReplicatedInput<T>::finalize_other(int player, T& target,
|
||||
inline void ReplicatedInput<T>::finalize_other(int player, T& target,
|
||||
octetStream& o)
|
||||
{
|
||||
typename T::value_type t;
|
||||
|
||||
@@ -28,7 +28,7 @@ protected:
|
||||
virtual void buffer_inverses(MAC_Check_Base<T>& MC, Player& P);
|
||||
|
||||
public:
|
||||
static const int buffer_size = 1000;
|
||||
static const int buffer_size = 10000;
|
||||
|
||||
virtual ~BufferPrep() {}
|
||||
|
||||
@@ -49,6 +49,8 @@ protected:
|
||||
typename T::Protocol* protocol;
|
||||
SubProcessor<T>* proc;
|
||||
|
||||
int base_player;
|
||||
|
||||
void buffer_triples();
|
||||
void buffer_squares();
|
||||
void buffer_inverses() { throw runtime_error("not inverses in rings"); }
|
||||
@@ -57,7 +59,7 @@ public:
|
||||
ReplicatedRingPrep(SubProcessor<T>* proc);
|
||||
virtual ~ReplicatedRingPrep() {}
|
||||
|
||||
void set_protocol(typename T::Protocol& protocol) { this->protocol = &protocol; }
|
||||
void set_protocol(typename T::Protocol& protocol);
|
||||
|
||||
virtual void buffer_bits();
|
||||
};
|
||||
|
||||
@@ -15,6 +15,16 @@ ReplicatedRingPrep<T>::ReplicatedRingPrep(SubProcessor<T>* proc) :
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ReplicatedRingPrep<T>::set_protocol(typename T::Protocol& protocol)
|
||||
{
|
||||
this->protocol = &protocol;
|
||||
if (proc)
|
||||
base_player = proc->Proc.thread_num;
|
||||
else
|
||||
base_player = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ReplicatedRingPrep<T>::buffer_triples()
|
||||
{
|
||||
@@ -90,7 +100,7 @@ void BufferPrep<T>::buffer_inverses(MAC_Check_Base<T>& MC, Player& P)
|
||||
MC.POpen(c_open, c, P);
|
||||
for (size_t i = 0; i < c.size(); i++)
|
||||
if (c_open[i] != 0)
|
||||
inverses.push_back({triples[i][0], triples[i][1] / c_open[i]});
|
||||
inverses.push_back({{triples[i][0], triples[i][1] / c_open[i]}});
|
||||
triples.clear();
|
||||
if (inverses.empty())
|
||||
throw runtime_error("products were all zero");
|
||||
@@ -141,25 +151,12 @@ void XOR(vector<T>& res, vector<T>& x, vector<T>& y, int buffer_size,
|
||||
res[i] = x[i] + y[i] - prot.finalize_mul() * two;
|
||||
}
|
||||
|
||||
int get_n_relevant_players(Player& P)
|
||||
{
|
||||
int n_relevant_players = P.num_players();
|
||||
try
|
||||
{
|
||||
n_relevant_players = ShamirMachine::s().threshold + 1;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
return n_relevant_players;
|
||||
}
|
||||
|
||||
template<template<class U> class T>
|
||||
void buffer_bits_spec(ReplicatedPrep<T<gfp>>& prep, vector<T<gfp>>& bits,
|
||||
typename T<gfp>::Protocol& prot)
|
||||
{
|
||||
(void) bits, (void) prot;
|
||||
if (get_n_relevant_players(prot.P) > 10)
|
||||
if (prot.get_n_relevant_players() > 10)
|
||||
{
|
||||
vector<array<T<gfp>, 2>> squares(prep.buffer_size);
|
||||
vector<T<gfp>> s;
|
||||
@@ -189,12 +186,12 @@ void ReplicatedRingPrep<T>::buffer_bits()
|
||||
auto buffer_size = this->buffer_size;
|
||||
auto& bits = this->bits;
|
||||
auto& P = protocol->P;
|
||||
int n_relevant_players = get_n_relevant_players(P);
|
||||
int n_relevant_players = protocol->get_n_relevant_players();
|
||||
vector<vector<T>> player_bits(n_relevant_players, vector<T>(buffer_size));
|
||||
typename T::Input input(proc, P);
|
||||
for (int i = 0; i < n_relevant_players; i++)
|
||||
for (int i = 0; i < P.num_players(); i++)
|
||||
input.reset(i);
|
||||
if (P.my_num() < n_relevant_players)
|
||||
if (positive_modulo(P.my_num() - base_player, P.num_players()) < n_relevant_players)
|
||||
{
|
||||
SeededPRNG G;
|
||||
for (int i = 0; i < buffer_size; i++)
|
||||
@@ -202,25 +199,28 @@ void ReplicatedRingPrep<T>::buffer_bits()
|
||||
input.send_mine();
|
||||
}
|
||||
for (int i = 0; i < n_relevant_players; i++)
|
||||
if (i == P.my_num())
|
||||
{
|
||||
int input_player = (base_player + i) % P.num_players();
|
||||
if (input_player == P.my_num())
|
||||
for (auto& x : player_bits[i])
|
||||
x = input.finalize_mine();
|
||||
else
|
||||
{
|
||||
octetStream os;
|
||||
P.receive_player(i, os, true);
|
||||
P.receive_player(input_player, os, true);
|
||||
for (auto& x : player_bits[i])
|
||||
input.finalize_other(i, x, os);
|
||||
input.finalize_other(input_player, x, os);
|
||||
}
|
||||
}
|
||||
auto& prot = *protocol;
|
||||
vector<T> tmp;
|
||||
XOR(tmp, player_bits[0], player_bits[1], buffer_size, prot, proc);
|
||||
for (int i = 2; i < n_relevant_players - 1; i++)
|
||||
XOR(tmp, tmp, player_bits[i], buffer_size, prot, proc);
|
||||
XOR(bits, tmp, player_bits[n_relevant_players - 1], buffer_size, prot, proc);
|
||||
XOR(bits, player_bits[0], player_bits[1], buffer_size, prot, proc);
|
||||
for (int i = 2; i < n_relevant_players; i++)
|
||||
XOR(bits, bits, player_bits[i], buffer_size, prot, proc);
|
||||
base_player++;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
void ReplicatedRingPrep<Rep3Share<gf2n>>::buffer_bits()
|
||||
{
|
||||
assert(protocol != 0);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Multiplication.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SPDZ.h"
|
||||
#include "Processor.h"
|
||||
#include "Math/Share.h"
|
||||
#include "Auth/MAC_Check.h"
|
||||
|
||||
#include "Input.hpp"
|
||||
|
||||
template class SPDZ<gfp>;
|
||||
template class SPDZ<gf2n>;
|
||||
@@ -19,7 +19,7 @@ template<class T> class ShamirInput;
|
||||
class Player;
|
||||
|
||||
template<class U>
|
||||
class Shamir : public PrepLessProtocol<ShamirShare<U>>
|
||||
class Shamir : public ProtocolBase<ShamirShare<U>>
|
||||
{
|
||||
typedef ShamirShare<U> T;
|
||||
|
||||
@@ -45,6 +45,8 @@ public:
|
||||
Shamir(Player& P);
|
||||
~Shamir();
|
||||
|
||||
int get_n_relevant_players();
|
||||
|
||||
void reset();
|
||||
|
||||
void init_mul(SubProcessor<T>* proc);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "Shamir.h"
|
||||
#include "ShamirInput.h"
|
||||
#include "ShamirMachine.h"
|
||||
#include "Machines/ShamirMachine.h"
|
||||
|
||||
template<class U>
|
||||
U Shamir<U>::get_rec_factor(int i, int n)
|
||||
@@ -31,6 +31,12 @@ Shamir<U>::~Shamir()
|
||||
delete resharing;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
int Shamir<U>::get_n_relevant_players()
|
||||
{
|
||||
return ShamirMachine::s().threshold + 1;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
void Shamir<U>::reset()
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
#include "ShamirInput.h"
|
||||
#include "ShamirMachine.h"
|
||||
#include "Machines/ShamirMachine.h"
|
||||
|
||||
template<class U>
|
||||
void ShamirInput<U>::reset(int player)
|
||||
|
||||
@@ -117,3 +117,17 @@ print_ln('weighted average: %s', result.reveal())
|
||||
|
||||
print_ln_if((sum(point[0] for point in data) == 0).reveal(), \
|
||||
'but the inputs were invalid (weights add up to zero)')
|
||||
|
||||
# permutation matrix
|
||||
|
||||
M = Matrix(2, 2, sfix)
|
||||
M[0][0] = 0
|
||||
M[1][0] = 1
|
||||
M[0][1] = 1
|
||||
M[1][1] = 0
|
||||
|
||||
# matrix multiplication
|
||||
|
||||
M = data * M
|
||||
test(M[0][0], data[0][1].reveal())
|
||||
test(M[1][1], data[1][0].reveal())
|
||||
|
||||
38
README.md
38
README.md
@@ -5,16 +5,40 @@ protocols such as SPDZ, MASCOT, Overdrive, BMR garbled circuits
|
||||
(evaluation only), Yao's garbled circuits, and computation based on
|
||||
semi-honest three-party replicated secret sharing (with an honest majority).
|
||||
|
||||
#### TL;DR
|
||||
#### TL;DR (Binary Distribution on Linux or Souce Distribution on macOS)
|
||||
|
||||
This requires `sudo` rights as well as a working toolchain installed
|
||||
for the first step, refer to [the requirements](#requirements)
|
||||
otherwise. It will execute [the
|
||||
This requires either a Linux distribution originally released 2011 or
|
||||
later (glibc 2.12) or macOS High Sierra or later as well as Python 2
|
||||
and basic command-line utilities.
|
||||
|
||||
Download and unpack the distribution, then execute the following from
|
||||
the top folder:
|
||||
|
||||
```
|
||||
Scripts/tldr.sh
|
||||
./compile.py tutorial
|
||||
echo 1 2 3 > Player-Data/Input-P0-0
|
||||
echo 1 2 3 > Player-Data/Input-P1-0
|
||||
Scripts/mal-rep-field.sh tutorial
|
||||
```
|
||||
|
||||
This runs [the tutorial](Programs/Source/tutorial.mpc) with three
|
||||
parties, an honest majority, and malicious security.
|
||||
|
||||
#### TL;DR (Source Distribution)
|
||||
|
||||
On Linux, this requires a working toolchain and [all
|
||||
requirements](#requirements). On Ubuntu, the following might suffice:
|
||||
```
|
||||
apt-get install automake build-essential git libboost-dev libboost-thread-dev libsodium-dev libssl-dev libtool m4 python texinfo yasm
|
||||
```
|
||||
On MacOS, this requires [brew](https://brew.sh) to be installed,
|
||||
which will be used for all dependencies.
|
||||
It will execute [the
|
||||
tutorial](Programs/Source/tutorial.mpc) with three
|
||||
parties, an honest majority, and malicious security.
|
||||
|
||||
```
|
||||
make -j 8 mpir
|
||||
make -j 8 tldr
|
||||
./compile.py tutorial
|
||||
Scripts/setup-replicated.sh
|
||||
@@ -95,10 +119,10 @@ phase outputs the amount of offline material required, which allows to
|
||||
compute the preprocessing time for a particulor computation.
|
||||
|
||||
#### Requirements
|
||||
- GCC 4.8 or later (tested with 7.3; remove `-no-pie` from `CONFIG` for GCC 4.8) or LLVM (tested with 6.0; remove `-no-pie` from `CONFIG`)
|
||||
- GCC 4.8 or later (tested with 7.3) or LLVM (tested with 6.0)
|
||||
- MPIR library, compiled with C++ support (use flag --enable-cxx when running configure)
|
||||
- libsodium library, tested against 1.0.16
|
||||
- OpenSSL, tested against 1.1.0
|
||||
- OpenSSL, tested against and 1.0.2 and 1.1.0
|
||||
- Boost.Asio with SSL support (`libboost-dev` on Ubuntu), tested against 1.65
|
||||
- Boost.Thread for BMR (`libboost-thread-dev` on Ubuntu), tested against 1.65
|
||||
- CPU supporting AES-NI, PCLMUL, AVX2
|
||||
|
||||
20
Scripts/build.sh
Executable file
20
Scripts/build.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
function build
|
||||
{
|
||||
echo ARCH = $1 >> CONFIG.mine
|
||||
echo GDEBUG = >> CONFIG.mine
|
||||
make clean
|
||||
rm -R static
|
||||
mkdir static
|
||||
make -j 12 static-hm
|
||||
mkdir bin
|
||||
dest=bin/`uname`-$2
|
||||
rm -R $dest
|
||||
mv static $dest
|
||||
strip $dest/*
|
||||
}
|
||||
|
||||
build '' amd64
|
||||
build '-msse4.1 -maes -mpclmul' aes
|
||||
build '-msse4.1 -maes -mpclmul -mavx -mavx2 -mbmi2' avx2
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "Math/gf2n.h"
|
||||
#include "Processor/Buffer.h"
|
||||
#include "Tools/Buffer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "Math/gfp.h"
|
||||
#include "Processor/Buffer.h"
|
||||
#include "Tools/Buffer.h"
|
||||
#include "Tools/ezOptionParser.h"
|
||||
#include "Math/Setup.h"
|
||||
|
||||
|
||||
@@ -54,4 +54,4 @@ SPDZROOT=${SPDZROOT:-.}
|
||||
|
||||
#. Scripts/setup.sh
|
||||
|
||||
mkdir logs
|
||||
mkdir logs 2> /dev/null
|
||||
|
||||
@@ -32,6 +32,3 @@ $HERE/setup-ssl.sh ${players}
|
||||
|
||||
$SPDZROOT/Fake-Offline.x ${players} -lgp ${bits} -lg2 ${g} --default ${default}
|
||||
|
||||
for i in $(seq 0 $[players-1]) ; do
|
||||
dd if=/dev/zero of=Player-Data/Private-Input-$i bs=10000 count=1
|
||||
done
|
||||
|
||||
@@ -10,4 +10,6 @@ for i in `seq 0 $[n-1]`; do
|
||||
openssl req -newkey rsa -nodes -x509 -out Player-Data/P$i.pem -keyout Player-Data/P$i.key -subj "/CN=P$i"
|
||||
done
|
||||
|
||||
# brew-installed OpenSSL on MacOS
|
||||
PATH=$PATH:/usr/local/opt/openssl/bin/
|
||||
c_rehash Player-Data
|
||||
|
||||
35
Scripts/tldr.sh
Executable file
35
Scripts/tldr.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `uname` = "Linux"; then
|
||||
flags='cat /proc/cpuinfo'
|
||||
elif test `uname` = Darwin; then
|
||||
if ! type brew; then
|
||||
echo Do you want me to install Homebrew?
|
||||
echo Press RETURN to continue or any other key to abort
|
||||
read ans
|
||||
if test "$ans"; then
|
||||
echo Aborting
|
||||
exit 1
|
||||
else
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
fi
|
||||
fi
|
||||
make tldr
|
||||
else
|
||||
echo OS unknown
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test "$flags"; then
|
||||
if $flags | grep -q avx2; then
|
||||
cpu=avx2
|
||||
elif $flags | grep -q aes; then
|
||||
cpu=aes
|
||||
else
|
||||
cpu=amd64
|
||||
fi
|
||||
|
||||
cp -av bin/`uname`-$cpu/* .
|
||||
fi
|
||||
|
||||
Scripts/setup-ssl.sh
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "Tools/Buffer.h"
|
||||
|
||||
bool BufferBase::rewind = false;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROCESSOR_BUFFER_H_
|
||||
#define PROCESSOR_BUFFER_H_
|
||||
#ifndef TOOLS_BUFFER_H_
|
||||
#define TOOLS_BUFFER_H_
|
||||
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
@@ -12,7 +12,7 @@ using namespace std;
|
||||
#include "Math/Share.h"
|
||||
#include "Math/field_types.h"
|
||||
#include "Tools/time-func.h"
|
||||
#include "config.h"
|
||||
#include "Processor/config.h"
|
||||
|
||||
#ifndef BUFFER_SIZE
|
||||
#define BUFFER_SIZE 101
|
||||
@@ -153,4 +153,4 @@ inline void Buffer<T,U>::input(U& a)
|
||||
next++;
|
||||
}
|
||||
|
||||
#endif /* PROCESSOR_BUFFER_H_ */
|
||||
#endif /* TOOLS_BUFFER_H_ */
|
||||
@@ -35,6 +35,7 @@ void aes_128_schedule( octet* key, const octet* userkey )
|
||||
__m128i *Key_Schedule = (__m128i*)key;
|
||||
temp1 = _mm_loadu_si128((__m128i*)userkey);
|
||||
Key_Schedule[0] = temp1;
|
||||
#ifdef __AES__
|
||||
temp2 = _mm_aeskeygenassist_si128 (temp1 ,0x1);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
Key_Schedule[1] = temp1;
|
||||
@@ -65,8 +66,13 @@ void aes_128_schedule( octet* key, const octet* userkey )
|
||||
temp2 = _mm_aeskeygenassist_si128 (temp1,0x36);
|
||||
temp1 = AES_128_ASSIST(temp1, temp2);
|
||||
Key_Schedule[10] = temp1;
|
||||
#else
|
||||
(void) temp2;
|
||||
throw runtime_error("need to compile with AES-NI support");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __AES__
|
||||
inline void KEY_192_ASSIST(__m128i* temp1, __m128i * temp2, __m128i * temp3)
|
||||
{ __m128i temp4;
|
||||
*temp2 = _mm_shuffle_epi32 (*temp2, 0x55);
|
||||
@@ -222,7 +228,7 @@ void aes_256_encrypt(octet* out, const octet* in, const octet* key)
|
||||
tmp = _mm_aesenclast_si128 (tmp,((__m128i*)key)[j]);
|
||||
_mm_storeu_si128 (&((__m128i*)out)[0],tmp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,10 +54,14 @@ __attribute__((optimize("unroll-loops")))
|
||||
inline __m128i aes_128_encrypt(__m128i in, const octet* key)
|
||||
{ __m128i& tmp = in;
|
||||
tmp = _mm_xor_si128 (tmp,((__m128i*)key)[0]);
|
||||
#ifdef __AES__
|
||||
int j;
|
||||
for(j=1; j <10; j++)
|
||||
{ tmp = _mm_aesenc_si128 (tmp,((__m128i*)key)[j]); }
|
||||
tmp = _mm_aesenclast_si128 (tmp,((__m128i*)key)[j]);
|
||||
#else
|
||||
throw runtime_error("need to compile with AES-NI support");
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -70,12 +74,17 @@ inline void ecb_aes_128_encrypt(__m128i* out, __m128i* in, const octet* key)
|
||||
__m128i tmp[N];
|
||||
for (int i = 0; i < N; i++)
|
||||
tmp[i] = _mm_xor_si128 (in[i],((__m128i*)key)[0]);
|
||||
#ifdef __AES__
|
||||
int j;
|
||||
for(j=1; j <10; j++)
|
||||
for (int i = 0; i < N; i++)
|
||||
tmp[i] = _mm_aesenc_si128 (tmp[i],((__m128i*)key)[j]);
|
||||
for (int i = 0; i < N; i++)
|
||||
out[i] = _mm_aesenclast_si128 (tmp[i],((__m128i*)key)[j]);
|
||||
#else
|
||||
(void) tmp, (void) out;
|
||||
throw runtime_error("need to compile with AES-NI support");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <int N>
|
||||
|
||||
@@ -201,8 +201,7 @@ void octetStream::exchange(T send_socket, T receive_socket, octetStream& receive
|
||||
if (sent < len)
|
||||
{
|
||||
size_t to_send = min(buffer_size, len - sent);
|
||||
send(send_socket, data + sent, to_send);
|
||||
sent += to_send;
|
||||
sent += send_non_blocking(send_socket, data + sent, to_send);
|
||||
}
|
||||
|
||||
// avoid extra branching, false before length received
|
||||
|
||||
@@ -10,10 +10,11 @@ using namespace std;
|
||||
|
||||
PRNG::PRNG() : cnt(0)
|
||||
{
|
||||
#ifdef __AES__
|
||||
#ifdef USE_AES
|
||||
useC=(Check_CPU_support_AES()==0);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void PRNG::ReSeed()
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
#define SEED_SIZE HASH_SIZE
|
||||
#define RAND_SIZE HASH_SIZE
|
||||
#else
|
||||
#ifdef __AES__
|
||||
#define PIPELINES 8
|
||||
#else
|
||||
#define PIPELINES 1
|
||||
#endif
|
||||
#define SEED_SIZE AES_BLK_SIZE
|
||||
#define RAND_SIZE (PIPELINES * AES_BLK_SIZE)
|
||||
#endif
|
||||
@@ -38,7 +42,11 @@ class PRNG
|
||||
octet random[RAND_SIZE] __attribute__((aligned (16)));
|
||||
|
||||
#ifdef USE_AES
|
||||
#ifdef __AES__
|
||||
bool useC;
|
||||
#else
|
||||
const static bool useC = true;
|
||||
#endif
|
||||
|
||||
// Two types of key schedule for the different implementations
|
||||
// of AES
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "GC/Instruction.hpp"
|
||||
#include "GC/Program.hpp"
|
||||
|
||||
#include "Processor/Instruction.hpp"
|
||||
|
||||
namespace GC
|
||||
{
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#include "GC/Secret.h"
|
||||
#include "Networking/Player.h"
|
||||
#include "OT/OTExtensionWithMatrix.h"
|
||||
#include "sys/sysinfo.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
using namespace GC;
|
||||
|
||||
@@ -66,7 +67,8 @@ public:
|
||||
const Key& get_delta() { return master.delta; }
|
||||
void store_gate(const YaoGate& gate);
|
||||
|
||||
int get_n_worker_threads() { return max(1, get_nprocs() / master.machine.nthreads); }
|
||||
int get_n_worker_threads()
|
||||
{ return max(1u, thread::hardware_concurrency() / master.machine.nthreads); }
|
||||
int get_threshold() { return master.threshold; }
|
||||
|
||||
long get_gate_id() { return gate_id(thread_num); }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user