From 392817e53467fb204b2a4177b21fe814e429db9f Mon Sep 17 00:00:00 2001 From: calctopian Date: Fri, 20 Oct 2017 05:25:20 +0200 Subject: [PATCH] Windows port Please note that the configure script may have some issues depending on your system: - x86_64-w64-mingw32-gcc.exe (64 bits): detected size_t is "unsigned long long" but the configure doesn't accept it and cil.ml doesn't recognize it. Edit the configure script, search for "real_type=" and explicitly declare it (e.g., "real_type='unsigned long'"). Then run: "./configure CC=x86_64-w64-mingw32-gcc.exe" and "make RELEASE=1" - i686-w64-mingw32 (32 bits): if you get the following error message "/usr/i686-w64-mingw32/sys-root/mingw/include/stdlib.h:336: Error: Undefined function", define out the function _abs64: #ifdef __MINGW_INTRIN_INLINE __MINGW_INTRIN_INLINE __int64 __cdecl _abs64(__int64 x) { return __builtin_llabs(x);} #endif Steps to generate oblivc.dll and oblivc.lib: x86_64-w64-mingw32-gcc.exe -c -g atomic_queue.c -o atomic_queue.o -I . x86_64-w64-mingw32-gcc.exe -c -g bcrandom.c -o bcrandom.o -I . x86_64-w64-mingw32-gcc.exe -c -g commitReveal.c -o commitReveal.o -I . x86_64-w64-mingw32-gcc.exe -c -g dualex.c -o dualex.o -I . x86_64-w64-mingw32-gcc.exe -c -g nnob.c -o nnob.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_bits.c -o obliv_bits.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_network_utils.c -o obliv_network_utils.o -I . x86_64-w64-mingw32-gcc.exe -c -g ot.c -o ot.o -I . x86_64-w64-mingw32-gcc.exe -c -g privacy-free.c -o privacy-free.o -I . x86_64-w64-mingw32-gcc.exe -c -g psi.c -o psi.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_add.c -o obliv_float_add.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_div.c -o obliv_float_div.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_eq.c -o obliv_float_eq.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_le.c -o obliv_float_le.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_lt.c -o obliv_float_lt.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_mult.c -o obliv_float_mult.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_neg.c -o obliv_float_neg.o -I . x86_64-w64-mingw32-gcc.exe -c -g obliv_float_sub.c -o obliv_float_sub.o -I . x86_64-w64-mingw32-gcc.exe -shared -g -o oblivc.dll *.o -Wl,--output-def,oblivc.def,--out-implib,oblivc.a -lgcrypt -pthread -lws2_32 lib /machine:x64 /def:oblivc.def Compiling with Obliv-C: Please note that the CIL compiler underlying Obliv-C doesn't support intrinsics: you may have to comment/define out all the intrinsics definitions from system's headers (e.g., avx512fintrin.h, avxintrin.h, emmintrin.h, f16cintrin.h, mm3dnow.h, xmmintrin.h) --- src/ext/oblivc/atomic_queue.h | 1 + src/ext/oblivc/obliv.h | 2 + src/ext/oblivc/obliv_bits.c | 117 ++++++++++++++++-- src/ext/oblivc/obliv_bits.h | 5 + src/ext/oblivc/obliv_common.h | 10 +- src/ext/oblivc/obliv_yao.h | 4 + src/ext/oblivc/ot.c | 2 +- src/ext/oblivc/psi.c | 5 + src/ext/oblivc/sort_r.h | 226 ++++++++++++++++++++++++++++++++++ 9 files changed, 361 insertions(+), 11 deletions(-) create mode 100644 src/ext/oblivc/sort_r.h diff --git a/src/ext/oblivc/atomic_queue.h b/src/ext/oblivc/atomic_queue.h index eff70a80b..f79ecf3be 100644 --- a/src/ext/oblivc/atomic_queue.h +++ b/src/ext/oblivc/atomic_queue.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include // What the heck! Why is there no small library already out there for this? diff --git a/src/ext/oblivc/obliv.h b/src/ext/oblivc/obliv.h index 157876180..e42517c39 100644 --- a/src/ext/oblivc/obliv.h +++ b/src/ext/oblivc/obliv.h @@ -27,6 +27,8 @@ void execDebugProtocol(ProtocolDesc* pd, protocol_run start, void* arg); void execNetworkStressProtocol(ProtocolDesc* pd, int bytecount, protocol_run start, void* arg); void execYaoProtocol(ProtocolDesc* pd, protocol_run start, void* arg); +void execYaoProtocol_Init(ProtocolDesc* pd, protocol_run start, void* arg); +void execYaoProtocol_End(ProtocolDesc* pd, protocol_run start, void* arg); void execYaoProtocol_noHalf(ProtocolDesc* pd, protocol_run start, void* arg); bool execDualexProtocol(ProtocolDesc* pd, protocol_run start, void* arg); bool execNpProtocol(ProtocolDesc* pd, protocol_run start, void* arg); diff --git a/src/ext/oblivc/obliv_bits.c b/src/ext/oblivc/obliv_bits.c index 7dea5008a..5e32ab21e 100644 --- a/src/ext/oblivc/obliv_bits.c +++ b/src/ext/oblivc/obliv_bits.c @@ -9,9 +9,11 @@ #include #include // for protoUseStdio() #include +#ifndef _WIN32 #include #include #include +#endif #include #include #include @@ -92,8 +94,13 @@ static int tcp2PSend(ProtocolTransport* pt,int dest,const void* s,size_t n) size_t n2=0; tcpt->needFlush=true; while(n>n2) { +#ifdef _WIN32 + int res = send(tcpt->sock, n2+(char*)s, n-n2, 0); + if(res<0) { perror("TCP write error: "); return res; } +#else int res = fwrite(n2+(char*)s,1,n-n2,tcpt->sockStream); if(res<0) { perror("TCP write error: "); return res; } +#endif n2+=res; } return n2; @@ -118,12 +125,17 @@ static int tcp2PRecv(ProtocolTransport* pt,int src,void* s,size_t n) } while(n>n2) { - res = fread(n2+(char*)s,1,n-n2, tcpt->sockStream); - if(res<0 || feof(tcpt->sockStream)) - { - perror("TCP read error: "); - return res; - } + #ifdef _WIN32 + res = recv(tcpt->sock, n2+(char*)s, n-n2, 0); + if(res<0) { perror("TCP read error: "); return res; } + #else + res = fread(n2+(char*)s,1,n-n2, tcpt->sockStream); + if(res<0 || feof(tcpt->sockStream)) + { + perror("TCP read error: "); + return res; + } + #endif n2+=res; } return res; @@ -132,7 +144,11 @@ static int tcp2PRecv(ProtocolTransport* pt,int src,void* s,size_t n) static int tcp2PFlush(ProtocolTransport* pt) { struct tcp2PTransport* tcpt = CAST(pt); +#ifndef _WIN32 return fflush(tcpt->sockStream); +#else + return 0; +#endif } static int tcp2PFlushProfiled(ProtocolTransport* pt) @@ -145,8 +161,13 @@ static int tcp2PFlushProfiled(ProtocolTransport* pt) static void tcp2PCleanup(ProtocolTransport* pt) { tcp2PTransport* t = CAST(pt); +#ifdef _WIN32 + shutdown(t->sock, SD_SEND); + if(!t->keepAlive) closesocket(t->sock); +#else fflush(t->sockStream); if(!t->keepAlive) fclose(t->sockStream); +#endif free(pt); } @@ -197,10 +218,12 @@ static tcp2PTransport* tcp2PNew(int sock,bool isClient, bool isProfiled) trans->sock = sock; trans->isProfiled=isProfiled; trans->isClient=isClient; +#ifndef _WIN32 trans->sockStream=fdopen(sock, "rb+"); +#endif trans->sinceFlush = 0; const int one=1; - setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&one,sizeof(one)); + setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(const char*)&one,sizeof(one)); /*setvbuf(trans->sockStream, trans->buffer, _IOFBF, BUFFER_SIZE);*/ return trans; } @@ -248,6 +271,12 @@ static int tcpConnect(struct sockaddr_in* sa) int protocolConnectTcp2P(ProtocolDesc* pd,const char* server,const char* port) { struct sockaddr_in sa; +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD(2, 0); + WSAStartup(wVersionRequested, &wsaData); +#endif if(getsockaddr(server,port,(struct sockaddr*)&sa)<0) return -1; // dns error int sock=tcpConnect(&sa); if(sock<0) return -1; protocolUseTcp2P(pd,sock,true); @@ -266,10 +295,24 @@ int protocolConnectTcp2PProfiled(ProtocolDesc* pd,const char* server,const char* // used as sock=tcpListenAny(...); sock2=accept(sock); ...; close(both); static int tcpListenAny(const char* portn) { +#ifdef _WIN32 + uint16_t port; +#else in_port_t port; +#endif int outsock; +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD(2, 0); + WSAStartup(wVersionRequested, &wsaData); +#endif if(sscanf(portn,"%hu",&port)<1) return -1; +#ifdef _WIN32 + if((outsock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) return -1; +#else if((outsock=socket(AF_INET,SOCK_STREAM,0))<0) return -1; +#endif int reuse = 1; if (setsockopt(outsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) { fprintf(stderr,"setsockopt(SO_REUSEADDR) failed\n"); return -1; } @@ -287,7 +330,11 @@ int protocolAcceptTcp2P(ProtocolDesc* pd,const char* port) listenSock = tcpListenAny(port); if((sock=accept(listenSock,0,0))<0) return -1; protocolUseTcp2P(pd,sock,false); +#ifdef WIN32 + closesocket(listenSock); +#else close(listenSock); +#endif return 0; } @@ -333,7 +380,12 @@ static int sockSplit(int sock,ProtocolTransport* t,bool isClient) if(transSend(t,0,&sa.sin_port,sizeof(sa.sin_port))<0) return -1; transFlush(t); int newsock = accept(listenSock,0,0); - close(listenSock); +#ifdef _WIN32 + shutdown(listenSock, SD_SEND); + closesocket(listenSock); +#else + close(listenSock); +#endif return newsock; } } @@ -1118,6 +1170,43 @@ void mainYaoProtocol(ProtocolDesc* pd, bool point_and_permute, start(arg); } +void mainYaoProtocol_Init(ProtocolDesc* pd, bool point_and_permute, + protocol_run start, void* arg) +{ + YaoProtocolDesc* ypd = pd->extra; + int me = pd->thisParty; + ypd->ownOT=false; + ypd->gcount = ypd->gcount_offset = ypd->icount = ypd->ocount = 0; + if(me==1) + { + gcry_randomize(ypd->R,YAO_KEY_BYTES,GCRY_STRONG_RANDOM); + gcry_randomize(ypd->I,YAO_KEY_BYTES,GCRY_STRONG_RANDOM); + if(point_and_permute) ypd->R[0] |= 1; // flipper bit + + if(ypd->sender.sender==NULL) + { ypd->ownOT=true; + ypd->sender = honestOTExtSenderAbstract(honestOTExtSenderNew(pd,2)); + } + }else + if(ypd->recver.recver==NULL) + { ypd->ownOT=true; + ypd->recver = honestOTExtRecverAbstract(honestOTExtRecverNew(pd,1)); + } + + currentProto = pd; +} + +void mainYaoProtocol_End(ProtocolDesc* pd, bool point_and_permute, + protocol_run start, void* arg) +{ + YaoProtocolDesc* ypd = pd->extra; + int me = pd->thisParty; + //if(ownOT) + { if(me==1) otSenderRelease(&ypd->sender); + else otRecverRelease(&ypd->recver); + } +} + void cleanupYaoProtocol(ProtocolDesc* pd) { YaoProtocolDesc* ypd = pd->extra; @@ -1134,6 +1223,18 @@ void execYaoProtocol(ProtocolDesc* pd, protocol_run start, void* arg) cleanupYaoProtocol(pd); } +void execYaoProtocol_Init(ProtocolDesc* pd, protocol_run start, void* arg) +{ + setupYaoProtocol(pd,true); + mainYaoProtocol_Init(pd,true,start,arg); +} + +void execYaoProtocol_End(ProtocolDesc* pd, protocol_run start, void* arg) +{ + mainYaoProtocol_End(pd,true,start,arg); + cleanupYaoProtocol(pd); +} + void execYaoProtocol_noHalf(ProtocolDesc* pd, protocol_run start, void* arg) { setupYaoProtocol(pd,false); diff --git a/src/ext/oblivc/obliv_bits.h b/src/ext/oblivc/obliv_bits.h index 3e7afa4d9..2e7ffe73f 100644 --- a/src/ext/oblivc/obliv_bits.h +++ b/src/ext/oblivc/obliv_bits.h @@ -2,6 +2,11 @@ #define OBLIV_BITS_H #define __oblivious_c +// To compile with x86_64-w64-mingw32-gcc.exe, it's necessary to explictly define the intrinsics from gcc builtins +#ifdef __CIL_COMPABILITY__ +#include +#endif + //void* memset(void* s, int c, size_t n); // Hack, had to declare memset #include // memset to zero #include diff --git a/src/ext/oblivc/obliv_common.h b/src/ext/oblivc/obliv_common.h index 9367590d4..b1c7d3dbf 100644 --- a/src/ext/oblivc/obliv_common.h +++ b/src/ext/oblivc/obliv_common.h @@ -34,8 +34,14 @@ static inline int transSend(ProtocolTransport* t,int d,const void* p,size_t n) { return t->send(t,d,p,n); } static inline int transRecv(ProtocolTransport* t,int s,void* p,size_t n) { return t->recv(t,s,p,n); } -static inline int transFlush(ProtocolTransport* t) - { if (t->flush) return t->flush(t); else return 0; } +static inline int transFlush(ProtocolTransport* t) { +#ifndef _WIN32 + if (t->flush) + return t->flush(t); + else +#endif + return 0; +} static inline int osend(ProtocolDesc* pd,int d,const void* p,size_t n) { return transSend(pd->trans,d,p,n); } static inline int orecv(ProtocolDesc* pd,int s,void* p,size_t n) diff --git a/src/ext/oblivc/obliv_yao.h b/src/ext/oblivc/obliv_yao.h index e40273224..8f42509ec 100644 --- a/src/ext/oblivc/obliv_yao.h +++ b/src/ext/oblivc/obliv_yao.h @@ -22,6 +22,10 @@ const char* yaoKeyOfBit(const OblivBit* b); extern void setupYaoProtocol(ProtocolDesc* pd,bool halfgates); extern void mainYaoProtocol(ProtocolDesc* pd, bool point_and_permute, protocol_run start, void* arg); +extern void mainYaoProtocol_Init(ProtocolDesc* pd, bool point_and_permute, + protocol_run start, void* arg); +extern void mainYaoProtocol_End(ProtocolDesc* pd, bool point_and_permute, + protocol_run start, void* arg); extern void cleanupYaoProtocol(ProtocolDesc* pd); extern bool yaoGenrRevealOblivBits(ProtocolDesc* pd, widest_t* dest,const OblivBit* o,size_t n,int party); diff --git a/src/ext/oblivc/ot.c b/src/ext/oblivc/ot.c index fbbe663cc..a71456212 100644 --- a/src/ext/oblivc/ot.c +++ b/src/ext/oblivc/ot.c @@ -116,7 +116,7 @@ void dhSend(gcry_mpi_point_t u,ProtocolDesc* pd,int party, } // Allocates a new gcry_mpi_t, and returns it gcry_mpi_point_t dhRecv(ProtocolDesc* pd,int party) -{ char buf[DHEltSerialBytes]; +{ char buf[DHEltSerialBytes] = {}; gcry_mpi_point_t x; orecv(pd,party,buf,DHEltSerialBytes); dhDeserialize(&x,buf); diff --git a/src/ext/oblivc/psi.c b/src/ext/oblivc/psi.c index 62fe11818..29f00bfcd 100644 --- a/src/ext/oblivc/psi.c +++ b/src/ext/oblivc/psi.c @@ -7,6 +7,7 @@ #include #include #include +#include // from https://github.com/noporpoise/sort_r #define HASH_ALGO GCRY_MD_SHA1 #define HASH_BITS 160 @@ -173,7 +174,11 @@ OcPsiResult* execPsiProtocol_DH(ProtocolDesc* pd, xchgPoints(pd,curve,your,nu,mine,ni); PointCompareArgs *args = pcaNew(curve); +#ifdef _WIN32 + sort_r(your,nu,nu*sizeof(gcry_mpi_point_t),compare_points,args); +#else qsort_r(your,nu,sizeof(*your),compare_points,args); +#endif OcPsiResult* res = ocPsiResultNew(niindices[res->n++] = order[i]; diff --git a/src/ext/oblivc/sort_r.h b/src/ext/oblivc/sort_r.h new file mode 100644 index 000000000..e1dc40b71 --- /dev/null +++ b/src/ext/oblivc/sort_r.h @@ -0,0 +1,226 @@ +/* Isaac Turner 29 April 2014 Public Domain */ +#ifndef SORT_R_H_ +#define SORT_R_H_ + +#include +#include + +/* + +sort_r function to be exported. + +Parameters: + base is the array to be sorted + nel is the number of elements in the array + width is the size in bytes of each element of the array + compar is the comparison function + arg is a pointer to be passed to the comparison function + +void sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg); + +*/ + +#define _SORT_R_INLINE inline + +#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \ + defined __FreeBSD__ || defined __DragonFly__) +# define _SORT_R_BSD +#elif (defined _GNU_SOURCE || defined __gnu_hurd__ || defined __GNU__ || \ + defined __linux__ || defined __MINGW32__ || defined __GLIBC__) +# define _SORT_R_LINUX +#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__) +# define _SORT_R_WINDOWS +# undef _SORT_R_INLINE +# define _SORT_R_INLINE __inline +#else + /* Using our own recursive quicksort sort_r_simple() */ +#endif + +#if (defined NESTED_QSORT && NESTED_QSORT == 0) +# undef NESTED_QSORT +#endif + +/* swap a, b iff a>b */ +/* __restrict is same as restrict but better support on old machines */ +static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w, + int (*compar)(const void *_a, const void *_b, + void *_arg), + void *arg) +{ + char tmp, *end = a+w; + if(compar(a, b, arg) > 0) { + for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; } + return 1; + } + return 0; +} + +/* Implement recursive quicksort ourselves */ +/* Note: quicksort is not stable, equivalent values may be swapped */ +static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, + int (*compar)(const void *_a, const void *_b, + void *_arg), + void *arg) +{ + char *b = (char *)base, *end = b + nel*w; + if(nel < 7) { + /* Insertion sort for arbitrarily small inputs */ + char *pi, *pj; + for(pi = b+w; pi < end; pi += w) { + for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {} + } + } + else + { + /* nel > 6; Quicksort */ + + /* Use median of first, middle and last items as pivot */ + char *x, *y, *xend, ch; + char *pl, *pr; + char *last = b+w*(nel-1), *tmp; + char *l[3]; + l[0] = b; + l[1] = b+w*(nel/2); + l[2] = last; + + if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; } + if(compar(l[1],l[2],arg) > 0) { + tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */ + if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; } + } + + /* swap l[id], l[2] to put pivot as last element */ + for(x = l[1], y = last, xend = x+w; xcompar)(a, b, ss->arg); + } + + #endif + + #if defined _SORT_R_LINUX + + typedef int(* __compar_d_fn_t)(const void *, const void *, void *); + extern void qsort_r(void *base, size_t nel, size_t width, + __compar_d_fn_t __compar, void *arg) + __attribute__((nonnull (1, 4))); + + #endif + + /* implementation */ + + static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg) + { + #if defined _SORT_R_LINUX + + #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8)) + + /* no qsort_r in glibc before 2.8, need to use nested qsort */ + sort_r_simple(base, nel, width, compar, arg); + + #else + + //qsort_r(base, nel, width, compar, arg); // no qsort_r on MinGW + sort_r_simple(base, nel, width, compar, arg); + + #endif + + #elif defined _SORT_R_BSD + + struct sort_r_data tmp; + tmp.arg = arg; + tmp.compar = compar; + qsort_r(base, nel, width, &tmp, sort_r_arg_swap); + + #elif defined _SORT_R_WINDOWS + + struct sort_r_data tmp; + tmp.arg = arg; + tmp.compar = compar; + qsort_s(base, nel, width, sort_r_arg_swap, &tmp); + + #else + + /* Fall back to our own quicksort implementation */ + sort_r_simple(base, nel, width, compar, arg); + + #endif + } + +#endif /* !NESTED_QSORT */ + +#undef _SORT_R_INLINE +#undef _SORT_R_WINDOWS +#undef _SORT_R_LINUX +#undef _SORT_R_BSD + +#endif /* SORT_R_H_ */