diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..91b9bf3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/externals/Miracl"] + path = src/externals/Miracl + url = git://github.com/CertiVox/Miracl.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3d3d2d3 --- /dev/null +++ b/Makefile @@ -0,0 +1,52 @@ + +BIN=bin +SRC=src +EXT=${SRC}/externals + +# compiler settings +CC=g++ +COMPILER_OPTIONS=-O2 +DEBUG_OPTIONS=-g3 -Wall +BATCH= + +ARCHITECTURE = $(shell uname -m) +ifeq (${ARCHITECTURE},x86_64) +MIRACL_MAKE:=linux64 +GNU_LIB_PATH:=x86_64 +else +MIRACL_MAKE:=linux +GNU_LIB_PATH:=i386 +endif + +INCLUDE=-I.. -I/usr/include/glib-2.0/ -I/usr/lib/${GNU_LIB_PATH}-linux-gnu/glib-2.0/include + + +LIBRARIES=-lgmp -lgmpxx -lpthread src/miracl_lib/miracl.a -L /usr/lib -lssl -lcrypto -lglib-2.0 +CFLAGS= + +# directory for the Miracl submodule and library +MIRACL_LIB_DIR=${EXT}/miracl_lib +SOURCES_MIRACL=${EXT}/Miracl/* +OBJECTS_MIRACL=${MIRACL_LIB_DIR}/*.o + +all: miracl + @echo "make all done." + +# this will create a copy of the files in ${SOURCES_MIRACL} and its sub-directories and put them into ${MIRACL_LIB_DIR} without sub-directories, then compile it +miracl: ${MIRACL_LIB_DIR}/miracl.a + +# copy Miracl files to a new directory (${CORE}/util/miracl_lib/), call the build script and delete everything except the archive, header and object files. +${MIRACL_LIB_DIR}/miracl.a: ${SOURCES_MIRACL} + @find ${EXT}/Miracl/ -type f -exec cp '{}' ${EXT}/miracl_lib \; + @cd ${EXT}/miracl_lib/; bash ${MIRACL_MAKE}; find . -type f -not -name '*.a' -not -name '*.h' -not -name '*.o' -not -name '.git*'| xargs rm + + +.PHONY: clean cleanall examples ${EXAMPLE_SUBDIRS} all ${TEST} miracl runtest core + +# only clean example objects, test object and binaries +clean: + rm -f ${OBJECTS_EXAMPLE} ${OBJECTS_TEST} ${BIN}/*.exe + +# this will clean everything: example objects, test object and binaries and the Miracl library +cleanall: cleanmore + rm -f ${OBJECTS_MIRACL} ${MIRACL_LIB_DIR}/*.a diff --git a/Makefile~ b/Makefile~ new file mode 100644 index 0000000..3d3d2d3 --- /dev/null +++ b/Makefile~ @@ -0,0 +1,52 @@ + +BIN=bin +SRC=src +EXT=${SRC}/externals + +# compiler settings +CC=g++ +COMPILER_OPTIONS=-O2 +DEBUG_OPTIONS=-g3 -Wall +BATCH= + +ARCHITECTURE = $(shell uname -m) +ifeq (${ARCHITECTURE},x86_64) +MIRACL_MAKE:=linux64 +GNU_LIB_PATH:=x86_64 +else +MIRACL_MAKE:=linux +GNU_LIB_PATH:=i386 +endif + +INCLUDE=-I.. -I/usr/include/glib-2.0/ -I/usr/lib/${GNU_LIB_PATH}-linux-gnu/glib-2.0/include + + +LIBRARIES=-lgmp -lgmpxx -lpthread src/miracl_lib/miracl.a -L /usr/lib -lssl -lcrypto -lglib-2.0 +CFLAGS= + +# directory for the Miracl submodule and library +MIRACL_LIB_DIR=${EXT}/miracl_lib +SOURCES_MIRACL=${EXT}/Miracl/* +OBJECTS_MIRACL=${MIRACL_LIB_DIR}/*.o + +all: miracl + @echo "make all done." + +# this will create a copy of the files in ${SOURCES_MIRACL} and its sub-directories and put them into ${MIRACL_LIB_DIR} without sub-directories, then compile it +miracl: ${MIRACL_LIB_DIR}/miracl.a + +# copy Miracl files to a new directory (${CORE}/util/miracl_lib/), call the build script and delete everything except the archive, header and object files. +${MIRACL_LIB_DIR}/miracl.a: ${SOURCES_MIRACL} + @find ${EXT}/Miracl/ -type f -exec cp '{}' ${EXT}/miracl_lib \; + @cd ${EXT}/miracl_lib/; bash ${MIRACL_MAKE}; find . -type f -not -name '*.a' -not -name '*.h' -not -name '*.o' -not -name '.git*'| xargs rm + + +.PHONY: clean cleanall examples ${EXAMPLE_SUBDIRS} all ${TEST} miracl runtest core + +# only clean example objects, test object and binaries +clean: + rm -f ${OBJECTS_EXAMPLE} ${OBJECTS_TEST} ${BIN}/*.exe + +# this will clean everything: example objects, test object and binaries and the Miracl library +cleanall: cleanmore + rm -f ${OBJECTS_MIRACL} ${MIRACL_LIB_DIR}/*.a diff --git a/src/bench_psi.cpp b/src/bench_psi.cpp new file mode 100644 index 0000000..100e818 --- /dev/null +++ b/src/bench_psi.cpp @@ -0,0 +1,425 @@ +/* + * bench_psi.cpp + * + * Created on: Nov 10, 2014 + * Author: mzohner + */ + +#include "bench_psi.h" + + +int32_t main(int32_t argc, char** argv) { + psi_demonstrator(argc, argv); + //benchroutine(argc, argv); +} + + + +int32_t benchroutine(int32_t argc, char** argv) { + uint32_t nelements=0, elebytelen=4, symsecbits=128, + intersect_size, i, ntasks=1, runs=1, j, protocol, nclients=2, pnelements; + uint8_t *elements, *intersection; + string address = "127.0.0.1"; + uint16_t port=7766; + timeval begin, end; + vector sockfd(ntasks); + field_type ftype = ECC_FIELD; + role_type role = (role_type) 0; + uint64_t bytes_sent=0, bytes_received=0, mbfac; + double epsilon=1.2; + bool cardinality=false; + bool detailed_timings = false; + + mbfac=1024*1024; + + read_bench_options(&argc, &argv, &role, &nelements, &elebytelen, &symsecbits, + &address, &port, &ntasks, &protocol, &nclients, &epsilon, &cardinality, &ftype, + &detailed_timings); + + if(role == SERVER) { + if(protocol == TTP) { + ntasks = nclients; + sockfd.resize(ntasks); + } + listen(address.c_str(), port, sockfd.data(), ntasks); + } else { + for(i = 0; i < ntasks; i++) + connect(address.c_str(), port, sockfd[i]); + } + + crypto crypto(symsecbits, (uint8_t*) const_seed); + + //exchange number of items, bit-length of items, symmetric security parameter and protocol to make sure the parameters are correct + if(protocol != TTP) { + pnelements = exchange_information(nelements, elebytelen, symsecbits, ntasks, protocol, sockfd[0]); + } + + if(protocol != TTP || role != SERVER) { + elements = (uint8_t*) calloc(nelements * elebytelen, sizeof(uint8_t)); + crypto.gen_rnd(elements, elebytelen * nelements); + } + + +#ifdef PRINT_INPUT_ELEMENTS + for(i = 0; i < nelements; i++) { + cout << "Element " << i << ": " << (hex); + for(j = 0; j < elebytelen; j++) + cout << (uint32_t) elements[i*elebytelen + j]; + cout << (dec) << endl; + } +#endif + +#ifndef BATCH + cout << "Benchmarking protocol " << protocol << " on " << runs << " runs" << endl; +#endif + gettimeofday(&begin, NULL); + for(i = 0; i < runs; i++) { + switch(protocol) { + case NAIVE: + naivepsi(role, nelements, pnelements, elebytelen, elements, &intersection, &crypto, sockfd.data(), ntasks); + break; + case TTP: + ttppsi(role, nelements, elebytelen, elements, &intersection, &crypto, sockfd.data(), nclients, cardinality); break; + case DH_ECC: + intersect_size = dhpsi(role, nelements, pnelements, elebytelen, elements, &intersection, &crypto, sockfd.data(), + ntasks, cardinality, ftype); + break; + case OT_PSI: + intersect_size = otpsi(role, nelements, pnelements, elebytelen*8, elements, &intersection, &crypto, sockfd.data(), + ntasks, epsilon, detailed_timings); + break; + default:break; + } + } + gettimeofday(&end, NULL); + + for(i = 0; i < sockfd.size(); i++) { + bytes_sent += sockfd[i].get_bytes_sent(); + bytes_received += sockfd[i].get_bytes_received(); + } +#ifdef BATCH + cout << getMillies(begin, end) << "\t" << ((double) bytes_sent + bytes_received)/mbfac << endl; + + +#else + cout << "Required time:\t" << fixed << std::setprecision(1) << getMillies(t_start, t_end)/1000 << " s" << endl; + cout << "Data sent:\t" << ((double)bytes_sent)/mbfac << " MB" << endl; + cout << "Data received:\t" << ((double)bytes_received)/mbfac << " MB" << endl; +#endif + +#ifdef PRINT_INTERSECTION + + cout << "Found " << intersect_size << " intersecting elements" << endl; + if(!cardinality) { + for(i = 0; i < intersect_size; i++) { + for(j = 0; j < elebytelen; j++) { + cout << (hex) << (uint32_t) intersection[i * elebytelen + j] << (dec); + } + cout << endl; + } + } +#endif + if(protocol != TTP || role != SERVER) { + free(elements); + } + return 0; +} + + + +int32_t psi_demonstrator(int32_t argc, char** argv) { + uint32_t nelements=0, elebytelen=16, symsecbits=128, intersect_size, i, j, ntasks=1, protocol=3, + pnelements, *elebytelens, *res_bytelens; + bool detailed_timings=false; + uint8_t **elements, **intersection; + string address="127.0.0.1"; + uint16_t port=7766; + timeval t_start, t_end; + vector sockfd(ntasks); + string filename; + uint64_t bytes_sent=0, bytes_received=0, mbfac; + role_type role = (role_type) 0; + double epsilon=1.2; + + mbfac=1024*1024; + + read_psi_demo_options(&argc, &argv, &role, &filename, &address, &nelements, &detailed_timings); + + if(role == SERVER) { + listen(address.c_str(), port, sockfd.data(), ntasks); + } else { + for(i = 0; i < ntasks; i++) + connect(address.c_str(), port, sockfd[i]); + } + + gettimeofday(&t_start, NULL); + + //read in files and get elements and byte-length from there + + read_elements(&elements, &elebytelens, &nelements, filename); + if(detailed_timings) { + gettimeofday(&t_end, NULL); + } + + pnelements = exchange_information(nelements, elebytelen, symsecbits, ntasks, protocol, sockfd[0]); + //cout << "Performing private set-intersection between " << nelements << " and " << pnelements << " element sets" << endl; + + if(detailed_timings) { + cout << "Time for reading elements:\t" << fixed << std::setprecision(2) << getMillies(t_start, t_end)/1000 << " s" << endl; + } + + crypto crypto(symsecbits, (uint8_t*) const_seed); + +#ifndef BATCH + cout << "Benchmarking protocol " << protocol << " on " << runs << " runs" << endl; +#endif + intersect_size = otpsi(role, nelements, pnelements, elebytelens, elements, &intersection, &res_bytelens, + &crypto, sockfd.data(), ntasks, epsilon, detailed_timings); + gettimeofday(&t_end, NULL); + + +#ifdef PRINT_INTERSECTION + if(role == CLIENT) { + //cout << "Computation finished. Found " << intersect_size << " intersecting elements:" << endl; + if(!detailed_timings) { + for(i = 0; i < intersect_size; i++) { + //cout << "\t"; + for(j = 0; j < res_bytelens[i]; j++) { + cout << intersection[i][j]; + } + cout << endl; + } + } + } +#endif + + for(i = 0; i < sockfd.size(); i++) { + bytes_sent += sockfd[i].get_bytes_sent(); + bytes_received += sockfd[i].get_bytes_received(); + } + + //cout << "Required time:\t" << fixed << std::setprecision(1) << getMillies(t_start, t_end)/1000 << " s" << endl; + //cout << "Data sent:\t" << ((double)bytes_sent)/mbfac << " MB" << endl; + //cout << "Data received:\t" << ((double)bytes_received)/mbfac << " MB" << endl; + + for(i = 0; i < nelements; i++) + free(elements[i]); + free(elements); + free(elebytelens); + return 1; +} + + +void read_elements(uint8_t*** elements, uint32_t** elebytelens, uint32_t* nelements, string filename) { + uint32_t i, j; + ifstream infile(filename.c_str()); + if(!infile.good()) { + cerr << "Input file " << filename << " does not exist, program exiting!" << endl; + exit(0); + } + string line; + if(*nelements == 0) { + while (std::getline(infile, line)) { + ++*nelements; + } + } + *elements=(uint8_t**) malloc(sizeof(uint8_t*)*(*nelements)); + *elebytelens = (uint32_t*) malloc(sizeof(uint32_t) * (*nelements)); + + infile.clear(); + infile.seekg(ios::beg); + for(i = 0; i < *nelements; i++) { + assert(std::getline(infile, line)); + (*elebytelens)[i] = line.length(); + (*elements)[i] = (uint8_t*) malloc((*elebytelens)[i]); + memcpy((*elements)[i], (uint8_t*) line.c_str(), (*elebytelens)[i]); + +#ifdef PRINT_INPUT_ELEMENTS + cout << "Element " << i << ": "; + for(j = 0; j < (*elebytelens)[i]; j++) + cout << (*elements)[i][j]; + cout << endl; +#endif + } +} + + + +uint32_t exchange_information(uint32_t myneles, uint32_t mybytelen, uint32_t mysecparam, uint32_t mynthreads, + uint32_t myprotocol, CSocket& sock) { + uint32_t pneles, pbytelen, psecparam, pnthreads, pprotocol; + //Send own values + sock.Send(&myneles, sizeof(uint32_t)); + sock.Send(&mybytelen, sizeof(uint32_t)); + sock.Send(&mysecparam, sizeof(uint32_t)); + sock.Send(&mynthreads, sizeof(uint32_t)); + sock.Send(&myprotocol, sizeof(uint32_t)); + + //Receive partner values + sock.Receive(&pneles, sizeof(uint32_t)); + sock.Receive(&pbytelen, sizeof(uint32_t)); + sock.Receive(&psecparam, sizeof(uint32_t)); + sock.Receive(&pnthreads, sizeof(uint32_t)); + sock.Receive(&pprotocol, sizeof(uint32_t)); + + //Assert + assert(mybytelen == pbytelen); + assert(mysecparam == psecparam); + assert(mynthreads == pnthreads); + assert(myprotocol == pprotocol); + + return pneles; +} + + +int32_t read_bench_options(int32_t* argcp, char*** argvp, role_type* role, uint32_t* nelements, uint32_t* bytelen, + uint32_t* secparam, string* address, uint16_t* port, uint32_t* ntasks, uint32_t* protocol, uint32_t* nclients, + double* epsilon, bool* cardinality, field_type* ftype, bool* detailed_timings) { + + uint32_t int_role=0, int_port=0; + bool useffc=false; + + parsing_ctx options[] = {{(void*) &int_role, T_NUM, 'r', "Role: 0/1", true, false}, + {(void*) protocol, T_NUM, 'p', "PSI protocol (0: Naive, 1: TTP, 2: DH, 3: OT)", true, false}, + {(void*) nelements, T_NUM, 'n', "Num elements", true, false}, + {(void*) bytelen, T_NUM, 'b', "Byte length", true, false}, + {(void*) secparam, T_NUM, 's', "Symmetric Security Bits", false, false}, + {(void*) address, T_STR, 'a', "IP-address", false, false}, + {(void*) &int_port, T_NUM, 'o', "Port", false, false}, + {(void*) ntasks, T_NUM, 't', "Number of threads", false, false}, + {(void*) nclients, T_NUM, 'c', "Number of clients for TTP based protocol", false, false}, + {(void*) epsilon, T_DOUBLE, 'e', "Epsilon in Cuckoo hashing", false, false}, + {(void*) cardinality, T_FLAG, 'y', "Compute cardinality (only for DH and TTP PSI)", false, false}, + {(void*) &useffc, T_FLAG, 'f', "Use finite-field cryptography", false, false}, + {(void*) detailed_timings, T_FLAG, 'd', "Enable Detailed Timings", false, false} + }; + + if(!parse_options(argcp, argvp, options, sizeof(options)/sizeof(parsing_ctx))) { + print_usage("PSI-Implementations", options, sizeof(options)/sizeof(parsing_ctx)); + cout << "Exiting" << endl; + exit(0); + } + + assert(int_role < 2); + *role = (role_type) int_role; + + assert(*protocol < PROT_LAST); + if(int_port != 0) { + assert(int_port < 1<<(sizeof(uint16_t)*8)); + *port = (uint16_t) int_port; + } + + if(useffc) { + *ftype = P_FIELD; + } + //delete options; + + return 1; +} + + +int32_t read_psi_demo_options(int32_t* argcp, char*** argvp, role_type* role, string* filename, string* address, + uint32_t* nelements, bool* detailed_timings) { + + uint32_t int_role; + //parsing_ctx *options = new parsing_ctx[5];//(parsing_ctx*) calloc(noptions, sizeof(parsing_ctx)); + + parsing_ctx options[] = {{(void*) &int_role, T_NUM, 'r', "Role: 0/1", true, false}, + {(void*) filename, T_STR, 'f', "Input file", true, false}, + {(void*) address, T_STR, 'a', "IP-address", false, false}, + {(void*) nelements, T_NUM, 'n', "Num elements", false, false}, + {(void*) detailed_timings, T_FLAG, 't', "Flag: Detailed timings", false, false} + }; + + if(!parse_options(argcp, argvp, options, sizeof(options)/sizeof(parsing_ctx))) { + print_usage("PSI_demo", options, sizeof(options)/sizeof(parsing_ctx)); + cout << "Exiting" << endl; + exit(0); + } + + assert(int_role < 2); + *role = (role_type) int_role; + + //delete options; + + return 1; +} + + + +int32_t parse_options(int32_t* argcp, char*** argvp, parsing_ctx* options, uint32_t nops) { + uint32_t result = 0; + bool skip; + uint32_t i; + if(*argcp < 2) + return -1; + + while((*argcp) > 1) + { + if ((*argvp)[1][0] != '-' || (*argvp)[1][1] == '\0' || (*argvp)[1][2] != '\0') + return result; + for(i = 0, skip=false; i < nops && !skip; i++) { + if( ((*argvp)[1][1]) == options[i].opt_name) { + switch(options[i].type) { + case T_NUM: + if (isdigit((*argvp)[2][0])) { + ++*argvp; + --*argcp; + *((uint32_t*) options[i].val) = atoi((*argvp)[1]); + } + break; + case T_DOUBLE: + ++*argvp; + --*argcp; + *((double*) options[i].val) = atof((*argvp)[1]); + break; + case T_STR: + ++*argvp; + --*argcp; + *((string*) options[i].val) = (*argvp)[1]; + break; + case T_FLAG: + *((bool*)options[i].val) = true; + break; + } + ++result; + ++*argvp; + --*argcp; + options[i].set=true; + skip = true; + } + } + } + + for(i = 0; i < nops; i++) { + if(options[i].required && !options[i].set) + return 0; + } + return 1; +} + + +void print_usage(string progname, parsing_ctx* options, uint32_t nops) { + uint32_t i; + cout << "Usage: ./"< +#include +#include + + +using namespace std; + +//#define PRINT_INPUT_ELEMENTS +//#define PRINT_INTERSECTION + +enum PSI_PROT {NAIVE=0, TTP=1, DH_ECC=2, OT_PSI=3, PROT_LAST=4}; +enum etype {T_NUM, T_STR, T_FLAG, T_DOUBLE}; + +typedef struct { + void* val; + etype type; + char opt_name; + string help_str; + bool required; + bool set; +} parsing_ctx; + + +int32_t benchroutine(int32_t argc, char** argv); +int32_t psi_demonstrator(int32_t argc, char** argv); + +void read_elements(uint8_t*** elements, uint32_t** elebytelens, uint32_t* nelements, string filename); + + +uint32_t exchange_information(uint32_t myneles, uint32_t mybytelen, uint32_t mysecparam, uint32_t mynthreads, + uint32_t myprotocol, CSocket& sock); + +void print_bench_usage(); +void print_demo_usage(); + +void print_usage(string progname, parsing_ctx* options, uint32_t nops); + +int32_t read_psi_demo_options(int32_t* argcp, char*** argvp, role_type* role, string* filename, string* address, + uint32_t* nelements, bool* detailed_timings); +int32_t read_bench_options(int32_t* argcp, char*** argvp, role_type* role, uint32_t* nelements, uint32_t* bytelen, + uint32_t* secparam, string* address, uint16_t* port, uint32_t* ntasks, uint32_t* protocol, uint32_t* nclients, + double* epsilon, bool* cardinality, field_type* ftype, bool* detailed_timings); + + +int32_t parse_options(int32_t* argcp, char*** argvp, parsing_ctx* options, uint32_t nops); + +#endif /* BENCH_PSI_H_ */ diff --git a/src/externals/Miracl b/src/externals/Miracl new file mode 160000 index 0000000..cff161b --- /dev/null +++ b/src/externals/Miracl @@ -0,0 +1 @@ +Subproject commit cff161bad6364548b361b63938a988db23f60c2a diff --git a/src/hashing/cuckoo.cpp b/src/hashing/cuckoo.cpp new file mode 100644 index 0000000..882628f --- /dev/null +++ b/src/hashing/cuckoo.cpp @@ -0,0 +1,196 @@ +/* + * cuckoo.cpp + * + * Created on: Oct 7, 2014 + * Author: mzohner + */ + +#include "cuckoo.h" + +//returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements +uint8_t* cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitlen, uint32_t *outbitlen, uint32_t* nelesinbin, + uint32_t* perm, uint32_t ntasks, prf_state_ctx* prf_state) +{ + //The resulting hash table + uint8_t* hash_table; + cuckoo_entry_ctx** cuckoo_table; + cuckoo_entry_ctx* cuckoo_entries; + uint32_t i, j; + uint32_t *perm_ptr; + pthread_t* entry_gen_tasks; + cuckoo_entry_gen_ctx* ctx; + hs_t hs; + +#ifdef COUNT_FAILS + uint32_t fails = 0; +#endif + + + init_hashing_state(&hs, neles, bitlen, nbins, prf_state); + *outbitlen = hs.outbitlen; + + cuckoo_table = (cuckoo_entry_ctx**) calloc(nbins, sizeof(cuckoo_entry_ctx*)); + cuckoo_entries = (cuckoo_entry_ctx*) malloc(neles * sizeof(cuckoo_entry_ctx)); + entry_gen_tasks = (pthread_t*) malloc(sizeof(pthread_t) * ntasks); + ctx = (cuckoo_entry_gen_ctx*) malloc(sizeof(cuckoo_entry_gen_ctx) * ntasks); + + //use the number of bins as address bits + //addr_bits = ceil_log2(nbins); + //cout << "Using addr_bits: " << hs.addrbitlen << endl; + //cout << "number of bins: " << nbins << ", address bits = " << addr_bits << endl; + //the remaining bits form the size of the values + + //inbytelen = ceil_divide(bitlen, 8); + //outbytelen = ceil_divide(outbitlen, 8); + //dummy_ele = (uint8_t*) malloc(ceil_divide(bitlen, 8)); + + for(i = 0; i < ntasks; i++) { + ctx[i].elements = elements; + ctx[i].cuckoo_entries = cuckoo_entries; + //ctx[i].inbitlen = bitlen; + // ctx[i].addr_bitlen = addr_bits; + //ctx[i].outbitlen = outbitlen; + //ctx[i].nbins = nbins; + ctx[i].hs = &hs; + ctx[i].startpos = i * ceil_divide(neles, ntasks); + ctx[i].endpos = min(ctx[i].startpos + ceil_divide(neles, ntasks), neles); + //cout << "Thread " << i << " starting from " << ctx[i].startpos << " going to " << ctx[i].endpos << " for " << neles << " elements" << endl; + if(pthread_create(entry_gen_tasks+i, NULL, gen_cuckoo_entries, (void*) (ctx+i))) { + cerr << "Error in creating new pthread at cuckoo hashing!" << endl; + exit(0); + } + } + + //generate the cuckoo entries for all elements + //for(i = 0; i < neles; i++) { + // gen_cuckoo_entry(elements + inbytelen * i, bitlen, addr_bits, cuckoo_entries + i, outbitlen, nbins, i); + //} + + for(i = 0; i < ntasks; i++) { + if(pthread_join(entry_gen_tasks[i], NULL)) { + cerr << "Error in joining pthread at cuckoo hashing!" << endl; + exit(0); + } + } + + //for(i = 0; i < nbins; i++) { + // cout << "Address " << i << " mapped to " << hs.address_used[i] << " times" << endl; + //} + //insert all elements into the cuckoo hash table + for(i = 0; i < neles; i++) { + if(!(insert_element(cuckoo_table, cuckoo_entries + i))) { +#ifdef COUNT_FAILS + fails++; + /*cout << "insertion failed for element " << (hex) << (*(((uint32_t*) elements)+i)) << ", inserting to address: "; + for(uint32_t j = 0; j < NUM_HASH_FUNCTIONS; j++) { + cout << (cuckoo_entries + i)->address[j] << ", "; + } + cout << (dec) << endl;*/ +#else + //cerr << "Insertion not successful for element " < 0) + cout << "insertion performed with " << fails << " fails" << endl; +#endif + + //Copy the final state of the cuckoo table into the hash table + perm_ptr = perm; + hash_table = (uint8_t*) calloc(nbins, hs.outbytelen); + + for(i = 0; i < nbins; i++) { + if(cuckoo_table[i] != NULL) { + memcpy(hash_table + i * hs.outbytelen, cuckoo_table[i]->val, hs.outbytelen); + //cout << "copying value: " << (hex) << (unsigned int) cuckoo_table[i]->val[cuckoo_table[i]->pos][0] << (dec) << endl; + *perm_ptr = cuckoo_table[i]->eleid; + perm_ptr++; + nelesinbin[i] = 1; + } else { + memset(hash_table + i * hs.outbytelen, DUMMY_ENTRY_CLIENT, hs.outbytelen); + nelesinbin[i] = 0; + } + } + + //Cleanup +#ifndef TEST_UTILIZATION + for(i = 0; i < neles; i++) { + //for(j = 0; j < NUM_HASH_FUNCTIONS; j++) { + free(cuckoo_entries[i].val); + //} + } +#endif + free(cuckoo_entries); + free(cuckoo_table); + free(entry_gen_tasks); + free(ctx); + + free_hashing_state(&hs); + + return hash_table; +} + + +void *gen_cuckoo_entries(void *ctx_void) { + cuckoo_entry_gen_ctx* ctx = (cuckoo_entry_gen_ctx*) ctx_void; + hs_t* hs = ctx->hs; + uint32_t i, inbytelen = ceil_divide(hs->inbitlen, 8); + uint8_t* eleptr = ctx->elements + inbytelen * ctx->startpos; + + + //generate the cuckoo entries for all elements + for(i = ctx->startpos; i < ctx->endpos; i++, eleptr+=inbytelen) { + gen_cuckoo_entry(eleptr, ctx->cuckoo_entries + i, hs, i); + } +} + + +inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint32_t ele_id) { + uint32_t i; + + out->pos = 0; + out->eleid = ele_id; + + //for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { +#ifndef TEST_UTILIZATION + out->val = (uint8_t*) malloc(hs->outbytelen); +#endif + hashElement(in, out->address, out->val, hs); + //} +} + +inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element) { + cuckoo_entry_ctx *evicted, *tmp_evicted; + uint32_t i, ev_pos, iter_cnt; +#ifdef DEBUG_CUCKOO + cout << "iter_cnt = " << iter_cnt << " for element " << (hex) << (*((uint32_t*) element->element)) << (dec) << ", inserting to address: " + << element->address[element->pos] << " or " << element->address[element->pos^1] << endl; +#endif + + for(iter_cnt = 0, evicted = element; iter_cnt < MAX_ITERATIONS; iter_cnt++) { + //TODO: assert(addr < MAX_TAB_ENTRIES) + for(i = 0; i < NUM_HASH_FUNCTIONS; i++) {//, ele_pos=(ele_pos+1)%NUM_HASH_FUNCTIONS) { + if(ctable[evicted->address[i]] == NULL) { + ctable[evicted->address[i]] = evicted; + evicted->pos = i; + return true; + } + } + + //choose random bin to evict other element + ev_pos = evicted->address[(evicted->pos^iter_cnt) % NUM_HASH_FUNCTIONS]; + + tmp_evicted = ctable[ev_pos]; + ctable[ev_pos] = evicted; + evicted = tmp_evicted; + + //change position - if the number of HF's is increased beyond 2 this should be replaced by a different strategy + evicted->pos = (evicted->pos+1) % NUM_HASH_FUNCTIONS; + } + + //the highest number of iterations has been reached + return false; +} diff --git a/src/hashing/cuckoo.h b/src/hashing/cuckoo.h new file mode 100644 index 0000000..cc0ddc3 --- /dev/null +++ b/src/hashing/cuckoo.h @@ -0,0 +1,60 @@ +/* + * cuckoo.h + * + * Created on: Oct 7, 2014 + * Author: mzohner + */ + +#ifndef CUCKOO_H_ +#define CUCKOO_H_ + +#include "hashing_util.h" + +#define MAX_ITERATIONS 1000 +//#define DEBUG_CUCKOO +//#define COUNT_FAILS + + +struct cuckoo_entry_ctx { + //id of the element in the source set + uint32_t eleid; + //addresses the bin of the cuckoo entry in the cuckoo table, will only work for up to 2^{32} bins + uint32_t address[NUM_HASH_FUNCTIONS]; + //the value of the entry + uint8_t* val; + //which position is the entry currently mapped to + uint32_t pos; +#ifdef DEBUG_CUCKOO + uint8_t* element; +#endif +}; + + +struct cuckoo_entry_gen_ctx { + //starting position in the generation process + uint32_t startpos; + //end position of entries that are generated by this thread + uint32_t endpos; + //input elements + uint8_t* elements; + //pointer to the cuckoo entries + cuckoo_entry_ctx* cuckoo_entries; + hs_t* hs; + //uint32_t inbitlen; + //uint32_t addr_bitlen; + //uint32_t outbitlen; + //uint32_t nbins; +}; + + +//returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements +uint8_t* cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitlen, uint32_t* outbitlen, uint32_t* nelesinbin, + uint32_t* perm, uint32_t ntasks, prf_state_ctx* prf_state); +//routine for generating the entries, is invoked by the threads +void *gen_cuckoo_entries(void *ctx); +inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint32_t ele_id); +inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element); + + + +#endif /* CUCKOO_H_ */ diff --git a/src/hashing/hashing_util.h b/src/hashing/hashing_util.h new file mode 100644 index 0000000..34d0dbe --- /dev/null +++ b/src/hashing/hashing_util.h @@ -0,0 +1,216 @@ +/* + * hashing_util.h + * + * Created on: Oct 8, 2014 + * Author: mzohner + */ + +#ifndef HASHING_UTIL_H_ +#define HASHING_UTIL_H_ + +#include "../util/typedefs.h" +#include "../util/crypto/crypto.h" + +typedef uint16_t TABLEID_T; + +#define NUM_HASH_FUNCTIONS 2 +#define MAX_TABLE_SIZE_BYTES sizeof(TABLEID_T) +#define DUMMY_ENTRY_SERVER 0x00 +#define DUMMY_ENTRY_CLIENT 0xFF + +#define USE_LUBY_RACKOFF +//#define TEST_UTILIZATION + +typedef struct hashing_state_ctx { + uint32_t** hf_values[NUM_HASH_FUNCTIONS]; + uint32_t nhfvals; + uint32_t nelements; + uint32_t nbins; + uint32_t inbitlen; + uint32_t addrbitlen; + uint32_t outbitlen; + //the byte values, are stored separately since they are needed very often + uint32_t inbytelen; + uint32_t addrbytelen; + uint32_t outbytelen; + uint32_t* address_used; +} hs_t; + +//TODO: generate these randomly for each execution and communicate them between the parties +static const uint32_t HF_MASKS[3] = {0x00000000, 0x33333333, 0x14894568}; + +//use as mask to address the bits in a uint32_t vector +static const uint32_t SELECT_BITS[33] = {0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, \ + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, \ + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, \ + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, \ + 0xFFFFFFFF }; + +//can also be computed as SELECT_BITS ^ 0xFFFFFFFF +static const uint32_t SELECT_BITS_INV[33] ={0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, \ + 0xFFFFFF00, 0xFFFFFFE00, 0xFFFFFC00, 0xFFFFF800, 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, \ + 0xFFFF0000, 0xFFFFE0000, 0xFFFC0000, 0xFFF80000, 0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000, \ + 0xFF000000, 0xFFE000000, 0xFC000000, 0xF8000000, 0xF0000000, 0xE0000000, 0xC0000000, 0x80000000, \ + 0x00000000 }; + + +//Init the values for the hash function +static void init_hashing_state(hs_t* hs, uint32_t nelements, uint32_t inbitlen, uint32_t nbins, + prf_state_ctx* prf_state) { + uint32_t i, j, nrndbytes; + hs->nelements = nelements; + hs->nbins = nbins; + + hs->inbitlen = inbitlen; + hs->addrbitlen = min((uint32_t) ceil_log2(nbins), inbitlen); + +#ifdef USE_LUBY_RACKOFF + hs->outbitlen = hs->inbitlen - hs->addrbitlen+1; +#else + hs->outbitlen = inbitlen; +#endif + //TODO prevent too much memory utilization + //assert(hs->outbitlen < 32); + //TODO: quickfix to enable hashing for large values + //hs->outbitlen = min((double) hs->outbitlen, (double) 24); + + hs->inbytelen = ceil_divide(hs->inbitlen, 8); + hs->addrbytelen = ceil_divide(hs->addrbitlen, 8); + hs->outbytelen = ceil_divide(hs->outbitlen, 8); + + hs->nhfvals = ceil_divide(hs->outbytelen, MAX_TABLE_SIZE_BYTES); + + + nrndbytes = (1<<(8*MAX_TABLE_SIZE_BYTES)) * sizeof(uint32_t); + + //cout << " random bytes: " << nrndbytes << endl; + //cout << "inbitlen = " << hs->inbitlen << ", outbitlen = " << hs->outbitlen << ", addrbitlen = " << hs->addrbitlen << + // ", nhfvals = " << hs->nhfvals << ", nrndbytes = " << nrndbytes << endl; + + for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { + hs->hf_values[i] = (uint32_t**) malloc(sizeof(uint32_t*) * hs->nhfvals); + + for(j = 0; j < hs->nhfvals; j++) { + hs->hf_values[i][j] = (uint32_t*) malloc(nrndbytes); + assert(hs->hf_values[i][j]); + gen_rnd_bytes(prf_state, (uint8_t*) hs->hf_values[i][j], nrndbytes); + } + } + //cout << "nhfvals = " << hs->nhfvals << endl; + hs->address_used = (uint32_t*) calloc(nbins, sizeof(uint32_t)); +} + +static void free_hashing_state(hs_t* hs) { + uint32_t i; + for(i = 0; i < NUM_HASH_FUNCTIONS; i++) + free(hs->hf_values[i]); +} + +//reduce the bit-length of the elements if some bits are used to determine the bin and a permutation is used for hashing +//static uint32_t getOutBitLen(uint32_t inbitlen, uint32_t nelements) { +// return inbitlen - ceil_log2(nelements); +//}; + +//TODO: a generic place holder, can be replaced by any other hash function +//inline void hashElement(uint8_t* element, uint32_t* address, uint8_t* val, uint32_t hfid, hs_t* hs) { +inline void hashElement(uint8_t* element, uint32_t* address, uint8_t* val, hs_t* hs) { + +#ifdef USE_LUBY_RACKOFF + //TODO: the table-lookup hashing is only used for elements up to 32-bit length, since it gets very inefficient for larger values + uint64_t i, j, L, R; + TABLEID_T hfmaskaddr; + //Store the first hs->addrbitlen bits in L + L = *((uint32_t*) element) & SELECT_BITS[hs->addrbitlen]; + //Store the remaining hs->outbitlen bits in R and pad correspondingly + R = (*((uint32_t*) element) & SELECT_BITS_INV[hs->addrbitlen]) >> (hs->addrbitlen); + + + //assert(R < (1<outbitlen)); + //cout << "R = " << R << endl; + /*if(hfid == 0) { + *address = L % hs->nbins; + *((uint32_t*) val) = R; + } else if(hfid == 1) { + *address = R % hs->nbins; + *((uint32_t*) val) = L; + } else { + *address = (L ^ R) % hs->nbins; + *((uint32_t*) val) = R; + }*/ + hfmaskaddr = R * sizeof(uint32_t); + //cout << "L = " << L << ", R = " << R << " addresses: "; + + for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { + //cout << "i = " << i << ", addrbytelen = " << hs->addrbytelen << ", R = " << R << ", nbins = " << + // hs->nbins << ", L = " << L << ", addr= " << endl; + //address[i] = (L ^ *(((uint32_t*) &(hs->hf_values[i][R*hs->addrbytelen])))) % hs->nbins; + for(j = 0; j < hs->nhfvals; j++) { + //assert(hfmaskaddr < (1<<(8*MAX_TABLE_SIZE_BYTES)) * hs->addrbytelen); + //cout << "i = " << i << ", j = " << j << ", Hfmaskaddr = " << hfmaskaddr << endl; + //cout << "Hfvalue: " << hs->hf_values[i][j][hfmaskaddr] << endl; + address[i] = (L ^ *((hs->hf_values[i][j]+hfmaskaddr))) % hs->nbins; + } + //cout << address[i] << ", "; + //hs->address_used[address[i]]++; + } + //cout << endl; + *((uint32_t*) val) = R; + //TODO copy remaining bits + + if(hs->outbytelen >= sizeof(uint32_t)) + memcpy(val + (sizeof(uint32_t) - hs->addrbytelen), element + sizeof(uint32_t), hs->outbytelen - sizeof(uint32_t)); + + //cout << "Address for hfid = " << hfid << ": " << *address << ", L = " << L << ", R = " << R << endl; + +#else + for(uint64_t i = 0; i < NUM_HASH_FUNCTIONS; i++) { + address[i] = ((*((uint32_t*) element+i) ^ HF_MASKS[i]) & SELECT_BITS[hs->addrbitlen]) % hs->nbins; + + #ifndef TEST_UTILIZATION + *((uint32_t*) val) = (*((uint32_t*) element) & SELECT_BITS_INV[hs->addrbitlen]) >> (hs->addrbitlen); + + //copy the remaining full bytes + if(hs->outbytelen >= sizeof(uint32_t)) + memcpy(val + (sizeof(uint32_t) - hs->addrbytelen), element + sizeof(uint32_t), hs->outbytelen - sizeof(uint32_t)); + #endif + } +#endif +} + +inline void domain_hashing(uint32_t nelements, uint8_t* elements, uint32_t elebytelen, uint8_t* result, + uint32_t resultbytelen, crypto* crypt) { + uint8_t *eleptr, *resultptr, *hash_buf; + uint32_t i; + + eleptr=elements; + resultptr = result; +#ifndef BATCH + cout << "Hashing " << nelements << " elements from " << elebytelen << " bytes into " << resultbytelen << " bytes" << endl; +#endif + hash_buf = (uint8_t*) calloc(crypt->get_hash_bytes(), sizeof(uint8_t)); + for(i = 0; i < nelements; i++, resultptr+=resultbytelen, eleptr+=elebytelen) { + memcpy(hash_buf, eleptr, elebytelen); + crypt->hash(resultptr, resultbytelen, hash_buf, elebytelen); + } + free(hash_buf); +} + +inline void domain_hashing(uint32_t nelements, uint8_t** elements, uint32_t* elebytelens, uint8_t* result, + uint32_t resultbytelen, crypto* crypt) { + uint8_t *resultptr;//, *hash_buf; + uint32_t i; + + //eleptr=elements; + resultptr = result; +#ifndef BATCH + cout << "Hashing " << nelements << " elements from " << elebytelen << " bytes into " << resultbytelen << " bytes" << endl; +#endif + //hash_buf = (uint8_t*) calloc(crypt->get_hash_bytes(), sizeof(uint8_t)); + for(i = 0; i < nelements; i++, resultptr+=resultbytelen) { + //memcpy(hash_buf, elements[i], elebytelens[i]); + crypt->hash(resultptr, resultbytelen, elements[i], elebytelens[i]); + } + //free(hash_buf); +} + +#endif /* HASHING_UTIL_H_ */ diff --git a/src/hashing/kcuckoo3a.C b/src/hashing/kcuckoo3a.C new file mode 100644 index 0000000..a2aaac3 --- /dev/null +++ b/src/hashing/kcuckoo3a.C @@ -0,0 +1,154 @@ +// K-ary cuckoo hashing (c) 2002-2003 by Peter Sanders +// this is a simple implementation for the purposes +// of measuring the performance of cuckoo hashing in abstract +// terms (number of probes per insert, storage efficiency) +// usage: compile using g++ or another ISO C++ compiler +// a.out +// there is also a constant tMax that defines the maximum number +// of trials for an insertion +// allocates space for n elements in K subtables, and repeats +// the follwing measurements repeat time: +// - find a hash function by filling full lookup tables +// with pseudo-random numbers. +// - insert elements i=0..n-1 into the table until this fails +// for the first time. (The cost of these insertions is not +// measured.) +// Every n/r successfully inserted elements, the follwing +// measurement is repeated n/r times: +// * a random element i2 is removed +// * the hash table entries for i2 are filled with new random values +// * i2 is reinserted. +// Note that this is equivalent to removing a random element +// inserting a new element that +// has never been in the table before. +// The output is a table that gives +// - x the number of elements in the table at each measuremnt interval +// - the average number of probes for an insertion during the measruements +// for the given number of inserted elements +// - K +// - n +// - repeat +// - seed +#define DEBUGLEVEL 1 +#include +#include +#include "util.h" +#include "mt-real.c" +#include + +#define split 1 + + +using namespace std; +const int tMax = 10000; // max number of random walk trials +int K; // number of probes +int n; // number of elements +int m; // number of elements per table +int **hash; // K times n array +int **table; // K times m array + + +// generate random int in 0..x-1 +inline int rand0K(int x) { return int(genrand()*x); } + + +// insert element i into table +// return value: +// -1 failure +// otherwise number of hash function evaluation +int insert(int i) { + int forbidden = -1; + int j = rand0K(K); + for (int t = 1; t <= tMax; t++) { + int p = hash [j][i]; + int newI = table[j][p]; + table[j][p] = i; // play the cuckoo + if (newI == -1) return t; // done + forbidden = j; + i = newI; // find new home for cuckoo victim + j = rand0K(K-1); + if (j == forbidden) j = K-1; + } + return tMax + 1; // insertion failed +} + +// remove element i from the table +void remove(int i) { + for (int j = 0; j < K; j++) { + int p = hash[j][i]; + if (table[j][p] == i) { + table[j][p] = -1; + return; + } + } +} + +/*int main(int argc, char **argv) { + int i, j; + assert(argc == 6); + K = atoi(argv[1]); // number of probes + n = atoi(argv[2]); // number of elements + // double eps = atof(argv[3]); // space slack + m = int(n/K + 0.5); + int r = atoi(argv[3]); // number of measured densities + int step = n/r; + int repeat = atoi(argv[4]); // how often to start from scratch + int seed = atoi(argv[5]); + sgenrand(seed); + cout << "# x tAvg(x) K N repeat seed" << endl; + + // allocate hash function and table + // and an empty table + hash = (int**) malloc(sizeof(int*) * K); + table = (int**) malloc(sizeof(int*) * K); + for (j = 0; j < K; j++) { + hash [j] = new int[n]; + table[j] = new int[m]; + } + + // initialize statistics + // sumT[i] is the average time for size i*step + double *sumT = new double[r+1]; + int *cf = new int[r+1]; + for (int i = 0; i < r; i++) { + sumT[i] = 0; + cf[i] = 0; + } + + // main loop + for (int rep = 0; rep < repeat; rep++) { + // init hash function and empty table + for (j = 0; j < K; j++) { + for (i = 0; i < n; i++) { hash [j][i] = rand0K(m); } + for (i = 0; i < m; i++) { table[j][i] = -1; } + } + + // fill table and keep measuring from time to time + for (i = 0; i < n; i++) { + if (insert(i) > tMax) break; // table is full + if (((i+1) % step) == 0) { // measure in detail here + for (int i1 = 0; i1 < step; i1++) { + // remove and reinsert a random element + int i2 = rand0K(i); + remove(i2); + for (j = 0; j < K; j++) hash[j][i2] = rand0K(m); + int t = insert(i2); + cf[i/step] += (t > tMax); + //cout << t << endl; + sumT[i/step] += t; + } + } + } + } + + for (int rep = 0; rep < r; rep++) { + cout << rep*step + step << " " + << sumT[rep]/step/repeat << " " + << K << " " + << n << " " + << repeat << " " + << seed << " " + << cf[rep] << endl; + } +} +*/ diff --git a/src/hashing/mt-real.c b/src/hashing/mt-real.c new file mode 100644 index 0000000..41bf1b1 --- /dev/null +++ b/src/hashing/mt-real.c @@ -0,0 +1,90 @@ +/* A C-program for MT19937B: Real number version */ +/* genrand() generate one pseudorandom number with double precision */ +/* which is uniformly distributed on [0,1]-interval for each call. */ +/* sgenrand(seed) set initial values to the working area of 624 words.*/ +/* sgenrand(seed) must be called once before calling genrand() */ +/* (seed is any integer except 0). */ + +/* + LICENCE CONDITIONS: + + Matsumoto and Nishimura consent to GNU General + Public Licence + + NOTE: + When you use it in your program, please let Matsumoto + know it. + + Because of a machine-trouble, Matsumoto lost emails + which arrived during May 28-29. +*/ + + +#include + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0df /* constant vector a */ +#define UPPER_MASK 0x80000000 /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffff /* least significant r bits */ + +/* for tempering */ +#define TEMPERING_MASK_B 0x9d2c5680 +#define TEMPERING_MASK_C 0xefc60000 +#define TEMPERING_SHIFT_U(y) (y >> 11) +#define TEMPERING_SHIFT_S(y) (y << 7) +#define TEMPERING_SHIFT_T(y) (y << 15) +#define TEMPERING_SHIFT_L(y) (y >> 18) + +static unsigned long ptgfsr[N]; /* set initial seeds: N = 624 words */ + +void +sgenrand(unsigned long seed) /* seed should not be 0 */ +{ + int k; + + /* setting initial seeds to ptgfsr[N] using */ + /* the generator Line 25 of Table 1 in */ + /* [KNUTH 1981, The Art of Computer Programming */ + /* Vol. 2 (2nd Ed.), pp102] */ + + ptgfsr[0]= seed & 0xffffffff; + for (k=1; k> 1) ^ mag01[y & 0x1]; + } + for (;kk> 1) ^ mag01[y & 0x1]; + } + y = (ptgfsr[N-1]&UPPER_MASK)|(ptgfsr[0]&LOWER_MASK); + ptgfsr[N-1] = ptgfsr[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + + k = 0; + } + + y = ptgfsr[k++]; + y ^= TEMPERING_SHIFT_U(y); + y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; + y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; + y &= 0xffffffff; /* you may delete this line if word size = 32 */ + y ^= TEMPERING_SHIFT_L(y); + + return ( (double)y / (unsigned long)0xffffffff ); +} + diff --git a/src/hashing/simple_hashing.cpp b/src/hashing/simple_hashing.cpp new file mode 100644 index 0000000..3d11f7c --- /dev/null +++ b/src/hashing/simple_hashing.cpp @@ -0,0 +1,178 @@ +/* + * simple_hashing.cpp + * + * Created on: Oct 8, 2014 + * Author: mzohner + */ + +#include "simple_hashing.h" + +uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint32_t *outbitlen, uint32_t* nelesinbin, uint32_t nbins, + uint32_t ntasks, prf_state_ctx* prf_state) { + sht_ctx* table; + //uint8_t** bin_content; + uint8_t *eleptr, *bin_ptr, *result, *res_bins; + uint32_t i, j, tmpneles; + sheg_ctx* ctx; + pthread_t* entry_gen_tasks; + hs_t hs; + + init_hashing_state(&hs, neles, bitlen, nbins, prf_state); + //Set the output bit-length of the hashed elements + *outbitlen = hs.outbitlen; + + entry_gen_tasks = (pthread_t*) malloc(sizeof(pthread_t) * ntasks); + ctx = (sheg_ctx*) malloc(sizeof(sheg_ctx) * ntasks); + table = (sht_ctx*) malloc(sizeof(sht_ctx) * ntasks); + + + + for(i = 0; i < ntasks; i++) { + init_hash_table(table + i, ceil_divide(neles, ntasks), &hs); + } + + //for(i = 0; i < nbins; i++) + // pthread_mutex_init(locks+i, NULL); + + //tmpbuf = (uint8_t*) malloc(table->outbytelen); + + for(i = 0; i < ntasks; i++) { + ctx[i].elements = elements; + ctx[i].table = table + i; + ctx[i].startpos = i * ceil_divide(neles, ntasks); + ctx[i].endpos = min(ctx[i].startpos + ceil_divide(neles, ntasks), neles); + ctx[i].hs = &hs; + + //cout << "Thread " << i << " starting from " << ctx[i].startpos << " going to " << ctx[i].endpos << " for " << neles << " elements" << endl; + if(pthread_create(entry_gen_tasks+i, NULL, gen_entries, (void*) (ctx+i))) { + cerr << "Error in creating new pthread at simple hashing!" << endl; + exit(0); + } + } + + for(i = 0; i < ntasks; i++) { + if(pthread_join(entry_gen_tasks[i], NULL)) { + cerr << "Error in joining pthread at simple hashing!" << endl; + exit(0); + } + } + + //for(i = 0, eleptr=elements; i < neles; i++, eleptr+=inbytelen) { + // insert_element(table, eleptr, tmpbuf); + //} + + //malloc and copy simple hash table into hash table + //bin_content = (uint8_t**) malloc(sizeof(uint8_t*) * nbins); + //*nelesinbin = (uint32_t*) malloc(sizeof(uint32_t) * nbins); + + res_bins = (uint8_t*) malloc(neles * NUM_HASH_FUNCTIONS * hs.outbytelen); + bin_ptr = res_bins; + + + for(i = 0; i < hs.nbins; i++) { + nelesinbin[i] = 0; + for(j = 0; j < ntasks; j++) { + tmpneles = (table +j)->bins[i].nvals; + nelesinbin[i] += tmpneles; + //bin_content[i] = (uint8_t*) malloc(nelesinbin[i] * table->outbytelen); + memcpy(bin_ptr, (table + j)->bins[i].values, tmpneles * hs.outbytelen); + bin_ptr += (tmpneles * hs.outbytelen); + } + //right now only the number of elements in each bin is copied instead of the max bin size + } + + for(j = 0; j < ntasks; j++) + free_hash_table(table + j); + free(table); + free(entry_gen_tasks); + free(ctx); + + //for(i = 0; i < nbins; i++) + // pthread_mutex_destroy(locks+i); + //free(locks); + + free_hashing_state(&hs); + + return res_bins; +} + +void *gen_entries(void *ctx_tmp) { + //Insert elements in parallel, use lock to communicate + uint8_t *tmpbuf, *eleptr; + sheg_ctx* ctx = (sheg_ctx*) ctx_tmp; + uint32_t i, inbytelen, *address; + + address = (uint32_t*) malloc(NUM_HASH_FUNCTIONS * sizeof(uint32_t)); + tmpbuf = (uint8_t*) malloc(ceil_divide(ctx->hs->outbitlen, 8)); //for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { + // tmpbuf[i] = (uint8_t*) malloc(ceil_divide(ctx->hs->outbitlen, 8)); + //} + + for(i = ctx->startpos, eleptr=ctx->elements, inbytelen=ctx->hs->inbytelen; i < ctx->endpos; i++, eleptr+=inbytelen) { + insert_element(ctx->table, eleptr, address, tmpbuf, ctx->hs); + } + free(tmpbuf); + free(address); +} + +inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, uint8_t* tmpbuf, hs_t* hs) { + uint32_t i, j; + bin_ctx* tmp_bin; + + hashElement(element, address, tmpbuf, hs); + + for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { + + tmp_bin=table->bins + address[i]; + //pthread_mutex_lock(locks + address[i]); + memcpy(tmp_bin->values + tmp_bin->nvals * hs->outbytelen, tmpbuf, hs->outbytelen); + for(j = 0; j < i; j++) { + if(address[i] == address[j]) { + memset(tmp_bin->values + tmp_bin->nvals * hs->outbytelen, DUMMY_ENTRY_SERVER, hs->outbytelen); + } + } + tmp_bin->nvals++; + //TODO: or simply allocate a bigger block of memory: table->maxbinsize * 2, left out for efficiency reasons + assert(tmp_bin->nvals < table->maxbinsize); + /*cout << "Inserted into bin: " << address << ": " << (hex); + for(uint32_t j = 0; j < table->outbytelen; j++) { + cout << (unsigned int) tmpbuf[j]; + } + cout << (dec) << endl;*/ + //pthread_mutex_unlock(locks + address[i]); + } +} + + +void init_hash_table(sht_ctx* table, uint32_t nelements, hs_t* hs) { + uint32_t i; + + //table->addrbitlen = ceil_log2(nbins); + //table->addrbytelen = ceil_divide(table->addrbitlen, 8); + //table->inbytelen = ceil_divide(inbitlen, 8); + if(ceil_divide(nelements, hs->nbins) < 3) + table->maxbinsize = 3*max(ceil_log2(nelements),3); + else + table->maxbinsize = 6*max((int) ceil_divide(nelements, hs->nbins), 3); + //cout << "maxbinsize = " << table->maxbinsize << endl; + //table->outbytelen = ceil_divide(getOutBitLen(inbitlen, nbins), 8); + table->nbins = hs->nbins; + + table->bins = (bin_ctx*) calloc(hs->nbins, sizeof(bin_ctx)); + + for(i = 0; i < hs->nbins; i++) { + table->bins[i].values = (uint8_t*) malloc(table->maxbinsize * hs->outbytelen); + } +} + +void free_hash_table(sht_ctx* table) { + uint32_t i; + //1. free the byte-pointers for the values in the bints + for(i = 0; i < table->nbins; i++) { + //if(table->bins[i].nvals > 0) + free(table->bins[i].values); + } + //2. free the bins + free(table->bins); + //3. free the actual table + //free(table); +} diff --git a/src/hashing/simple_hashing.h b/src/hashing/simple_hashing.h new file mode 100644 index 0000000..7b7038e --- /dev/null +++ b/src/hashing/simple_hashing.h @@ -0,0 +1,54 @@ +/* + * simle_hashing.h + * + * Created on: Oct 8, 2014 + * Author: mzohner + */ + +#ifndef SIMLE_HASHING_H_ +#define SIMLE_HASHING_H_ + +#include "hashing_util.h" + +struct bin_ctx { + //hash-values of all elements mapped to this bin + uint8_t* values; + //number of elements stored in this bin + uint32_t nvals; +}; + +typedef struct simple_hash_table_ctx { + //pointer to the bins in the hash table + bin_ctx* bins; + //number bins in the hash table + uint32_t nbins; + //max bin size + uint32_t maxbinsize; + //uint32_t addrbitlen; + //uint32_t addrbytelen; + //uint32_t inbytelen; + //uint32_t outbytelen; +} sht_ctx; + +typedef struct simple_hash_entry_gen_ctx { + sht_ctx* table; + //input elements + uint8_t* elements; + uint32_t startpos; + uint32_t endpos; + //uint32_t inbytelen; + hs_t* hs; +} sheg_ctx; + + + +//returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements +uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint32_t* outbitlen, uint32_t* nelesinbin, uint32_t nbins, + uint32_t ntasks, prf_state_ctx* prf_state); +//routine for generating the entries, is invoked by the threads +void *gen_entries(void *ctx); +void init_hash_table(sht_ctx* table, uint32_t nelements, hs_t* hs); +void free_hash_table(sht_ctx* table); +inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, uint8_t* tmpbuf, hs_t* hs); + +#endif /* SIMLE_HASHING_H_ */ diff --git a/src/hashing/util.h b/src/hashing/util.h new file mode 100644 index 0000000..d069410 --- /dev/null +++ b/src/hashing/util.h @@ -0,0 +1,103 @@ +// this files contains all the application independent little +// functions and macros used for the optimizer. +// In particular Peters debug macros and Dags stuff +// from dbasic.h cdefs, random,... + +//////////////// stuff originally from debug.h /////////////////////////////// +// (c) 1997 Peter Sanders +// some little utilities for debugging adapted +// to the paros conventions + + +#ifndef UTIL +#define UTIL + +// default debug level. will be overidden e.g. if debug.h is included +#ifndef DEBUGLEVEL +#define DEBUGLEVEL 3 +#endif + +#if DEBUGLEVEL >= 0 +#define Debug0(A) A +#else +#define Debug0(A) +#endif +#if DEBUGLEVEL >= 1 +#define Debug1(A) A +#else +#define Debug1(A) +#endif +#if DEBUGLEVEL >= 2 +#define Debug2(A) A +#else +#define Debug2(A) +#endif +#if DEBUGLEVEL >= 3 +#define Debug3(A) A +#else +#define Debug3(A) +#endif +#if DEBUGLEVEL >= 4 +#define Debug4(A) A +#else +#define Debug4(A) +#endif +#if DEBUGLEVEL >= 5 +#define Debug5(A) A +#else +#define Debug5(A) +#endif +#if DEBUGLEVEL >= 6 +#define Debug6(A) A +#else +#define Debug6(A) +#endif + +#define Assert(c) if(!(c))\ + {cout << "\nAssertion violation " << __FILE__ << ":" << __LINE__ << endl;} +#define Assert0(C) Debug0(Assert(C)) +#define Assert1(C) Debug1(Assert(C)) +#define Assert2(C) Debug2(Assert(C)) +#define Assert3(C) Debug3(Assert(C)) +#define Assert4(C) Debug4(Assert(C)) +#define Assert5(C) Debug5(Assert(C)) + +#define Error(s) {cout << "\nError:" << s << " " << __FILE__ << ":" << __LINE__ << endl;} + +////////////// min, max etc. ////////////////////////////////////// + +#ifndef Max +#define Max(x,y) ((x)>=(y)?(x):(y)) +#endif + +#ifndef Min +#define Min(x,y) ((x)<=(y)?(x):(y)) +#endif + +#ifndef Abs +#define Abs(x) ((x) < 0 ? -(x) : (x)) +#endif + +#ifndef PI +#define PI 3.1415927 +#endif + +// is this the right definition of limit? +inline double limit(double x, double bound) +{ + if (x > bound) { return bound; } + else if (x < -bound) { return -bound; } + else return x; +} + +/////////////////////// timing ///////////////////// +#include + + +// elapsed CPU time see also /usr/include/sys/time.h +inline double cpuTime() +{ + return clock() * 1e-6; +} + +#endif diff --git a/src/naive-hashing/naive-psi.cpp b/src/naive-hashing/naive-psi.cpp new file mode 100644 index 0000000..ebdf05f --- /dev/null +++ b/src/naive-hashing/naive-psi.cpp @@ -0,0 +1,218 @@ +/* + * naive-psi.cpp + * + * Created on: Jul 9, 2014 + * Author: mzohner + */ +#include "naive-psi.h" + + +uint32_t naivepsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t elebytelen, uint8_t* elements, + uint8_t** result, crypto* crypt_env, CSocket* sock, uint32_t ntasks) { + + uint32_t i, intersect_size, maskbytelen; + task_ctx_naive ectx; + CSocket* tmpsock = sock; + + uint32_t* perm; + uint8_t *permeles, *hashes, *phashes; + + maskbytelen = ceil_divide(crypt_env->get_seclvl().statbits + ceil_log2(neles) + ceil_log2(pneles), 8); + + permeles = (uint8_t*) malloc(sizeof(uint8_t) * neles * elebytelen); + hashes = (uint8_t*) malloc(sizeof(uint8_t) * neles * maskbytelen); + perm = (uint32_t*) malloc(sizeof(uint32_t) * neles); + + + /* Permute the elements */ + crypt_env->gen_rnd_perm(perm, neles); + for(i = 0; i < neles; i++) { + memcpy(permeles + perm[i] * elebytelen, elements + i * elebytelen, elebytelen); + } + + /* Hash elements */ +#ifdef DEBUG + cout << "Hashing my elements" << endl; +#endif + + ectx.eles.input = permeles; + ectx.eles.inbytelen = elebytelen; + ectx.eles.outbytelen = maskbytelen, + ectx.eles.nelements = neles; + ectx.eles.output = hashes; + ectx.hctx.symcrypt = crypt_env; + + run_task_naive(ntasks, ectx, hash_naive); + + phashes = (uint8_t*) malloc(sizeof(uint8_t) * pneles * maskbytelen); + + +#ifdef DEBUG + cout << "Exchanging hashes" << endl; +#endif + snd_and_rcv_naive(hashes, neles * maskbytelen, phashes, pneles * maskbytelen, tmpsock); + + /*cout << "Hashes of my elements: " << endl; + for(i = 0; i < neles; i++) { + for(uint32_t j = 0; j < maskbytelen; j++) { + cout << (hex) << (uint32_t) hashes[i * maskbytelen + j] << (dec); + } + cout << endl; + }*/ + + /*cout << "Hashes of partner elements: " << endl; + for(i = 0; i < npeles; i++) { + for(uint32_t j = 0; j < hash_bytes; j++) { + cout << (hex) << (uint32_t) phashes[i * hash_bytes + j] << (dec); + } + cout << endl; + }*/ +#ifdef DEBUG + cout << "Finding intersection" << endl; +#endif + intersect_size = find_intersection_naive(elements, result, elebytelen, hashes, + neles, phashes, pneles, maskbytelen, perm); + + +#ifdef DEBUG + cout << "Free-ing allocated memory" << endl; +#endif + free(perm); + free(hashes); + free(permeles); + free(phashes); + + return intersect_size; +} + + + +uint32_t find_intersection_naive(uint8_t* elements, uint8_t** result, uint32_t elebytelen, uint8_t* hashes, + uint32_t neles, uint8_t* phashes, uint32_t pneles, uint32_t hashbytelen, uint32_t* perm) { + + uint32_t* invperm = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint64_t* tmpval; + + uint32_t size_intersect, i, intersect_ctr; + + for(i = 0; i < neles; i++) { + invperm[perm[i]] = i; + } + //cout << "My number of elements. " << neles << ", partner number of elements: " << pneles << ", maskbytelen: " << hashbytelen << endl; + + GHashTable *map= g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL); + for(i = 0; i < neles; i++) { + g_hash_table_insert(map,(void*) ((uint64_t*) &(hashes[i*hashbytelen])), &(invperm[i])); + } + + //for(i = 0; i < pneles; i++) { + // ((uint64_t*) &(phashes[i*hashbytelen]))[0]++; + //} + + for(i = 0, intersect_ctr = 0; i < pneles; i++) { + + if(g_hash_table_lookup_extended(map, (void*) ((uint64_t*) &(phashes[i*hashbytelen])), + NULL, (void**) &tmpval)) { + matches[intersect_ctr] = tmpval[0]; + intersect_ctr++; + //assert(intersect_ctr <= min(neles, pneles)); + } + } + + size_intersect = intersect_ctr; + + //result = (uint8_t**) malloc(sizeof(uint8_t*)); + (*result) = (uint8_t*) malloc(sizeof(uint8_t) * size_intersect * elebytelen); + for(i = 0; i < size_intersect; i++) { + memcpy((*result) + i * elebytelen, elements + matches[i] * elebytelen, elebytelen); + } + + free(invperm); + free(matches); + return size_intersect; +} + +void snd_and_rcv_naive(uint8_t* snd_buf, uint32_t snd_bytes, uint8_t* rcv_buf, uint32_t rcv_bytes, CSocket* sock) { + pthread_t snd_task; + bool created, joined; + snd_ctx_naive ctx; + + //Start new sender thread + ctx.sock = sock; + ctx.snd_buf = snd_buf; + ctx.snd_bytes = snd_bytes; + created = !pthread_create(&snd_task, NULL, send_data_naive, (void*) &(ctx)); + + //receive + sock->Receive(rcv_buf, rcv_bytes); + assert(created); + + joined = !pthread_join(snd_task, NULL); + assert(joined); + +} + +void run_task_naive(uint32_t nthreads, task_ctx_naive context, void* (*func)(void*) ) { + task_ctx_naive* contexts = (task_ctx_naive*) malloc(sizeof(task_ctx_naive) * nthreads); + pthread_t* threads = (pthread_t*) malloc(sizeof(pthread_t) * nthreads); + uint32_t i, neles_thread, electr, neles_cur; + bool created, joined; + + neles_thread = ceil_divide(context.eles.nelements, nthreads); + for(i = 0, electr = 0; i < nthreads; i++) { + neles_cur = min(context.eles.nelements - electr, neles_thread); + memcpy(contexts + i, &context, sizeof(task_ctx_naive)); + contexts[i].eles.nelements = neles_cur; + contexts[i].eles.input = context.eles.input + (context.eles.inbytelen * electr); + contexts[i].eles.output = context.eles.output + (context.eles.outbytelen * electr); + electr += neles_cur; + } + + for(i = 0; i < nthreads; i++) { + created = !pthread_create(threads + i, NULL, func, (void*) &(contexts[i])); + } + + assert(created); + + for(i = 0; i < nthreads; i++) { + joined = !pthread_join(threads[i], NULL); + } + + assert(joined); + + free(threads); + free(contexts); +} + +void *hash_naive(void* context) { +#ifdef DEBUG + cout << "Hashing thread started" << endl; +#endif + crypto* crypt_env = ((task_ctx_naive*) context)->hctx.symcrypt; + element_ctx_naive electx = ((task_ctx_naive*) context)->eles; + + uint8_t *inptr=electx.input, *outptr=electx.output; + uint32_t i; + + for(i = 0; i < electx.nelements; i++, inptr+=electx.inbytelen, outptr+=electx.outbytelen) { + crypt_env->hash(outptr, electx.outbytelen, inptr, electx.inbytelen); + } + return 0; +} + +void *send_data_naive(void* context) { + snd_ctx_naive *ctx = (snd_ctx_naive*) context; + ctx->sock->Send(ctx->snd_buf, ctx->snd_bytes); + return 0; +} + + + + +void print_naive_psi_usage() { + cout << "Usage: ./naivepsi [0 (server)/1 (client)] [num_elements] " << + "[element_byte_length] [sym_security_bits] [server_ip] [server_port]" << endl; + cout << "Program exiting" << endl; + exit(0); +} diff --git a/src/naive-hashing/naive-psi.h b/src/naive-hashing/naive-psi.h new file mode 100644 index 0000000..a43fc55 --- /dev/null +++ b/src/naive-hashing/naive-psi.h @@ -0,0 +1,60 @@ +/* + * naive-psi.h + * + * Created on: Jul 9, 2014 + * Author: mzohner + */ + +#ifndef NAIVE_PSI_H_ +#define NAIVE_PSI_H_ + + +#include "../util/typedefs.h" +#include "../util/connection.h" +#include "../util/crypto/crypto.h" +#include "../util/crypto/pk-crypto.h" +#include + + + +struct element_ctx_naive { + uint32_t nelements; + uint32_t inbytelen; + uint8_t* input; + uint32_t outbytelen; + uint8_t* output; +}; + +struct hash_ctx_naive { + crypto* symcrypt; +}; + +struct task_ctx_naive { + element_ctx_naive eles; + hash_ctx_naive hctx; +}; + +struct snd_ctx_naive { + uint8_t* snd_buf; + uint32_t snd_bytes; + CSocket* sock; +}; + +//TODO merge with dhpsi + +void print_naive_psi_usage(); +uint32_t naivepsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t elebytelen, uint8_t* elements, + uint8_t** result, crypto* crypt_env, CSocket* sock, uint32_t ntasks); +void run_task_naive(uint32_t nthreads, task_ctx_naive context, void* (*func)(void*) ); +void permute_naive(uint32_t nelements, uint32_t bytelen, uint8_t* elements, uint8_t* result, uint32_t* perm); +uint32_t find_intersection_naive(uint8_t* elements, uint8_t** result, uint32_t elebytelen, uint8_t* hashes, + uint32_t neles, uint8_t* phashes, uint32_t peles, uint32_t hashbytelen, uint32_t* perm); +void snd_and_rcv_naive(uint8_t* snd_buf, uint32_t snd_bytes, uint8_t* rcv_buf, uint32_t rcv_bytes, CSocket* sock); +void *hash_naive(void* context); +void *send_data_naive(void* context); + + + + + +#endif /* NAIVE_PSI_H_ */ diff --git a/src/ot-based/ot-psi.cpp b/src/ot-based/ot-psi.cpp new file mode 100644 index 0000000..32fa3e4 --- /dev/null +++ b/src/ot-based/ot-psi.cpp @@ -0,0 +1,855 @@ +/* + * ot-psi.cpp + * + * Created on: Jul 16, 2014 + * Author: mzohner + */ + +#include "ot-psi.h" + +/*int32_t main(int32_t argc, char** argv) { + uint32_t pid, nelements=10, elebytelen=4, symsecbits=80, + intersect_size, i, ntasks=1, runs=1, j; + int32_t nargs=8; + uint8_t *elements, *intersection; + const char* address; + uint16_t port; + timeval begin, end; + //CSocket* sockfd = (CSocket*) malloc(sizeof(CSocket) * ntasks); + vector sockfd(ntasks); + role_type role = (role_type) 0; + double epsilon=1.2; + + if(argc < nargs) { + print_ot_psi_usage(); + } + + pid = atoi(argv[1]); + nelements = atoi(argv[2]); + elebytelen = atoi(argv[3]); + symsecbits = atoi(argv[4]); + address = argv[5]; + port = (uint16_t) atoi(argv[6]); + epsilon = atof(argv[7]); + ntasks=atoi(argv[8]); + + if(pid == 0) { + role = SERVER; + listen(address, port, sockfd.data(), ntasks); + } else { + role = CLIENT; + for(i = 0; i < ntasks; i++) + connect(address, port, sockfd[i]); + } + + crypto crypto(symsecbits);//, const_ot_psi_seed); + elements = (uint8_t*) calloc(nelements * elebytelen, sizeof(uint8_t)); + +#ifdef SET_INPUT_ELEMENTS + for(i = 0; i < nelements; i++) { + //for(j = 0; j < elebytelen; j++) + elements[i*elebytelen] = i; + } +#endif +#ifdef PRINT_INPUT_ELEMENTS + for(i = 0; i < nelements; i++) { + cout << "Element " << i << ": " << (hex); + for(j = 0; j < elebytelen; j++) + cout << (unsigned int) elements[i*elebytelen + j]; + cout << (dec) << endl; + } +#endif + + + gettimeofday(&begin, NULL); + for(i = 0; i < runs; i++) { + crypto.gen_rnd(elements, elebytelen * nelements); + intersect_size = otpsi(nelements, elebytelen*8, elements, &intersection, &crypto, sockfd.data(), role, ntasks, epsilon); + } + gettimeofday(&end, NULL); + cout << "Computing the intersection took " << getMillies(begin, end) << " ms" << endl; + +#ifdef PRINT_INTERSECTION + cout << "Intersecting elements" << endl; + for(i = 0; i < intersect_size; i++) { + for(j = 0; j < elebytelen; j++) { + cout << (hex) << (uint32_t) intersection[i * elebytelen + j] << (dec); + } + cout << endl; + } +#endif + return 0; +}*/ + + +uint32_t otpsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t* elebytelens, uint8_t** elements, + uint8_t*** result, uint32_t** res_bytelen, crypto* crypt_env, CSocket* sock, uint32_t ntasks, double epsilon, + bool detailed_timings) { + + prf_state_ctx prf_state; + uint32_t maskbytelen, nbins, intersect_size, internal_bitlen, maskbitlen, *res_pos, i, elebytelen; + uint8_t *eleptr; + timeval t_start, t_end; + + + DETAILED_TIMINGS = (detailed_timings>0); + + + maskbitlen = pad_to_multiple(crypt_env->get_seclvl().statbits + ceil_log2(neles) + ceil_log2(pneles), 8); + maskbytelen = ceil_divide(maskbitlen, 8); + + //Hash elements into a smaller domain + eleptr = (uint8_t*) malloc(maskbytelen * neles); + + //cout << "Hashing " << neles << " elements with arbitrary bit-length into " << + // maskbitlen << " bit representation " << endl; + + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } + domain_hashing(neles, elements, elebytelens, eleptr, maskbytelen, crypt_env); + internal_bitlen = maskbitlen; + + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for domain hashing:\t" << fixed << std::setprecision(2) << getMillies(t_start, t_end) << " ms" << endl; + } + + crypt_env->gen_common_seed(&prf_state, sock[0]); + + if(role == SERVER) { + nbins = ceil(epsilon * pneles); + otpsi_server(eleptr, neles, nbins, pneles, internal_bitlen, maskbitlen, crypt_env, sock, ntasks, + &prf_state); + } else { //playing as client + nbins = ceil(epsilon * neles); + intersect_size = otpsi_client(eleptr, neles, nbins, pneles, internal_bitlen, maskbitlen, crypt_env, + sock, ntasks, &prf_state, &res_pos); + + std::sort(res_pos, res_pos+intersect_size); + + *result = (uint8_t**) malloc(intersect_size * sizeof(uint8_t*)); + *res_bytelen = (uint32_t*) malloc(intersect_size * sizeof(uint32_t)); + for(i = 0; i < intersect_size; i++) { + (*res_bytelen)[i] = elebytelens[res_pos[i]]; + (*result)[i] = (uint8_t*) malloc((*res_bytelen)[i]); + memcpy((*result)[i], elements[res_pos[i]], (*res_bytelen)[i]); + } + } + + free(eleptr); + + return intersect_size; +} + + + +uint32_t otpsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t elebitlen, uint8_t* elements, + uint8_t** result, crypto* crypt_env, CSocket* sock, uint32_t ntasks, double epsilon, + bool detailed_timings) { + + prf_state_ctx prf_state; + uint32_t maskbytelen, nbins, intersect_size, internal_bitlen, maskbitlen, *res_pos, i, elebytelen; + uint8_t *eleptr; + timeval t_start, t_end; + + DETAILED_TIMINGS = detailed_timings; + + maskbitlen = pad_to_multiple(crypt_env->get_seclvl().statbits + ceil_log2(neles) + ceil_log2(pneles), 8); + maskbytelen = ceil_divide(maskbitlen, 8); + elebytelen = ceil_divide(elebitlen, 8); + + if(elebitlen > maskbitlen) { + //Hash elements into a smaller domain + eleptr = (uint8_t*) malloc(maskbytelen * neles); + domain_hashing(neles, elements, ceil_divide(elebitlen, 8), eleptr, maskbytelen, crypt_env); + internal_bitlen = maskbitlen; +#ifndef BATCH + cout << "Hashing " << neles << " elements with " << elebitlen << " bit-length into " << + maskbitlen << " representation " << endl; +#endif + } else { + eleptr = elements; + internal_bitlen = elebitlen; + } + + + crypt_env->gen_common_seed(&prf_state, sock[0]); + + if(role == SERVER) { + nbins = ceil(epsilon * pneles); + otpsi_server(eleptr, neles, nbins, pneles, internal_bitlen, maskbitlen, crypt_env, sock, ntasks, + &prf_state); + } else { //playing as client + nbins = ceil(epsilon * neles); + intersect_size = otpsi_client(eleptr, neles, nbins, pneles, internal_bitlen, maskbitlen, crypt_env, + sock, ntasks, &prf_state, &res_pos); + *result = (uint8_t*) malloc(intersect_size * elebytelen); + for(i = 0; i < intersect_size; i++) { + memcpy((*result) + i * elebytelen, elements + res_pos[i] * elebytelen, elebytelen); + } + } + + if(elebitlen > maskbitlen) + free(eleptr); + + return intersect_size; +} + + + +uint32_t otpsi_client(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t pneles, + uint32_t elebitlen, uint32_t maskbitlen, crypto* crypt_env, CSocket* sock, uint32_t ntasks, + prf_state_ctx* prf_state, uint32_t** result) { + + uint32_t outbitlen, maskbytelen, intersect_size; + uint8_t *hash_table, *masks; + uint32_t* nelesinbin; + uint8_t *server_masks; + uint32_t* perm = (uint32_t*) calloc(neles, sizeof(uint32_t)); + pthread_t rcv_masks_thread; + pthread_t* query_map_thread = (pthread_t*) malloc(sizeof(pthread_t) * ntasks); + query_ctx* query_data = (query_ctx*) malloc(sizeof(query_ctx) * ntasks); + mask_rcv_ctx rcv_ctx; + timeval t_start, t_end; + + nelesinbin = (uint32_t*) calloc(nbins, sizeof(uint32_t)); + maskbytelen = ceil_divide(maskbitlen, 8); + intersect_size=0; + +#ifdef TIMING + gettimeofday(&t_start, NULL); +#endif + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } + hash_table = cuckoo_hashing(elements, neles, nbins, elebitlen, &outbitlen, + nelesinbin, perm, ntasks, prf_state); + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for Cuckoo hashing:\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } + +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Client: time for cuckoo hashing: " << getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); +#endif +#ifdef PRINT_BIN_CONTENT + print_bin_content(hash_table, nbins, ceil_divide(outbitlen, 8), NULL, false); +#endif + + masks = (uint8_t*) malloc(neles * maskbytelen); + //Perform the OPRG execution + oprg_client(hash_table, nbins, neles, nelesinbin, outbitlen, maskbitlen, crypt_env, sock, ntasks, masks); + + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Client: time for OPRG evaluation: " << getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + +#endif + //receive server masks + server_masks = (uint8_t*) malloc(NUM_HASH_FUNCTIONS * pneles * maskbytelen); + + //receive_masks(server_masks, NUM_HASH_FUNCTIONS * neles, maskbytelen, sock[0]); + //use a separate thread to receive the server's masks + rcv_ctx.rcv_buf = server_masks; + rcv_ctx.nmasks = NUM_HASH_FUNCTIONS * pneles; + rcv_ctx.maskbytelen = maskbytelen; + rcv_ctx.sock = sock; + if(pthread_create(&rcv_masks_thread, NULL, receive_masks, (void*) (&rcv_ctx))) { + cerr << "Error in creating new pthread at cuckoo hashing!" << endl; + exit(0); + } + //meanwhile generate the hash table + //GHashTable* map = otpsi_create_hash_table(ceil_divide(inbitlen,8), masks, neles, maskbytelen, perm); + //intersect_size = otpsi_find_intersection(eleptr, result, ceil_divide(inbitlen,8), masks, neles, server_masks, + // neles * NUM_HASH_FUNCTIONS, maskbytelen, perm); + //wait for receiving thread + if(pthread_join(rcv_masks_thread, NULL)) { + cerr << "Error in joining pthread at cuckoo hashing!" << endl; + exit(0); + } + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for receiving masks:\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Client: time for receiving masks and generating hash table: " << getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); +#endif +#ifdef PRINT_RECEIVED_VALUES + cout << "Received server masks: " << endl; + print_bin_content(server_masks, NUM_HASH_FUNCTIONS*neles, maskbytelen, NULL, false); +#endif + + //query hash table using multiple threads + //TODO set the values in the struct correct + /*for(i = 0; i < ntasks; i++) { + neles_per_thread = i * ceil_divide(pneles, ntasks); + thread_startpos = i * neles_per_thread; + query_data[i].elebytelen = ceil_divide(inbitlen,8); + query_data[i].elements = eleptr; + query_data[i].hashbytelen = maskbytelen; + query_data[i].map = map; + query_data[i].qhashes = server_masks + (thread_startpos * NUM_HASH_FUNCTIONS * maskbytelen); + query_data[i].qneles = min(neles - thread_startpos, neles_per_thread) * NUM_HASH_FUNCTIONS;//neles * NUM_HASH_FUNCTIONS; + if(pthread_create(query_map_thread+i, NULL, otpsi_query_hash_table, (void*) (query_data+i))) { + cerr << "Error in creating new pthread at cuckoo hashing!" << endl; + exit(0); + } + }*/ +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Client: time for computing intersection: " << getMillies(t_start, t_end) << " ms" << endl; +#endif + + //compute intersection + intersect_size = otpsi_find_intersection(result, masks, neles, server_masks, + neles * NUM_HASH_FUNCTIONS, maskbytelen, perm); + + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for intersecting:\t\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + } + free(masks); + free(hash_table); + free(nelesinbin); + free(perm); + free(server_masks); + free(query_map_thread); + free(query_data); + //free(map); + + return intersect_size; +} + + + +void otpsi_server(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t pneles, uint32_t elebitlen, uint32_t maskbitlen, + crypto* crypt_env, CSocket* sock, uint32_t ntasks, prf_state_ctx* prf_state) { + uint8_t *hash_table, *masks; + uint32_t* nelesinbin; + uint32_t outbitlen, maskbytelen; + timeval t_start, t_end; + + nelesinbin = (uint32_t*) malloc(sizeof(uint32_t) * nbins); + maskbytelen = ceil_divide(maskbitlen, 8); + + //outbitlen = getOutBitLen(inbitlen, nbins);//bitlen - addr_bits; + + //hash_table = (uint8_t*) malloc(nbins * NUM_HASH_FUNCTIONS * ceil_divide(outbitlen, 8)); + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } +#ifdef TIMING + gettimeofday(&t_start, NULL); +#endif + hash_table = simple_hashing(elements, neles, elebitlen, &outbitlen, nelesinbin, nbins, ntasks, prf_state); + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for simple hashing:\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Server: time for simple hashing: " << getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); +#endif +#ifdef PRINT_BIN_CONTENT + print_bin_content(hash_table, nbins, ceil_divide(outbitlen, 8), nelesinbin, true); +#endif + masks = (uint8_t*) malloc(NUM_HASH_FUNCTIONS * neles * maskbytelen); + oprg_server(hash_table, nbins, neles * NUM_HASH_FUNCTIONS, nelesinbin, outbitlen, maskbitlen, crypt_env, sock, ntasks, masks); + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Server: time for OPRG evaluation: " << getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); +#endif + //send the masks to the receiver + send_masks(masks, neles * NUM_HASH_FUNCTIONS, maskbytelen, sock[0]); + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for sending masks:\t\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + } +#ifdef TIMING + gettimeofday(&t_end, NULL); + cout << "Server: time for sending masks: " << getMillies(t_start, t_end) << " ms" << endl; +#endif + + free(masks); + free(hash_table); + free(nelesinbin); +} + + + + + +void print_ot_psi_usage() { + cout << "Usage: ./otpsi [0 (server)/1 (client)] [num_elements] [element_byte_length] " + << "[sym_security_bits] [server_ip] [server_port] [CH_epsilon] [nthreads]" << endl; + cout << "Program exiting" << endl; + exit(0); +} + + + +void oprg_client(uint8_t* hash_table, uint32_t nbins, uint32_t neles, uint32_t* nelesinbin, uint32_t elebitlen, + uint32_t maskbitlen, crypto* crypt, CSocket* sock, uint32_t nthreads, uint8_t* res_buf) { + CBitVector choices; + CBitVector resulting_masks; + uint32_t OTsPerElement, numOTs, i, u, maskbytelen, ctr; + uint8_t *keyMtx; + OTExtension1ooNECCReceiver* receiver; + timeval t_start, t_end; + + maskbytelen = ceil_divide(maskbitlen, 8); + + OTsPerElement = ceil_divide(elebitlen, 8); + numOTs = nbins * OTsPerElement; + +#ifndef BATCH + cout << "Client: bins = " << nbins << ", elebitlen = " << elebitlen << " and maskbitlen = " << + maskbitlen << " and performs " << numOTs << " OTs" << endl; +#endif + + keyMtx = (uint8_t*) malloc(crypt->get_aes_key_bytes()*m_nCodeWordBits* 2); + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } + + InitOTReceiver(keyMtx, sock[0], crypt); + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for base-OTs:\t\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } + + receiver = new OTExtension1ooNECCReceiver(m_nCodeWordBits, crypt, sock, keyMtx); + + //TODO recheck size + choices.AttachBuf(hash_table, ceil_divide(numOTs * 8, 8)); + + //for(uint32_t i = 0; i < nbins; i++) { + resulting_masks.AttachBuf(res_buf, neles * maskbytelen);//[i].Create(maskbitlen); + resulting_masks.Reset(); + //} + + //cout << "Choices: "; + //choices.PrintHex(); + + CBitVector response; + response.Create(numOTs, AES_BITS); + + //uint32_t itembitlen, uint32_t maskbitlen, CBitVector* results, crypto* crypt + //m_fMaskFct = new XORMasking(bitlength, m_cCrypto); + OPEMasking* mskfct = new OPEMasking(elebitlen, maskbitlen, nbins, nelesinbin, resulting_masks, crypt); + //choices.Reset(); + +// ObliviouslyReceive(choices, response, numOTs, AES_BITS, RN_OT); + //cout << "Receiver performing " << numOTs << " ots" << endl; + receiver->receive(numOTs, AES_BITS, choices, response, RN_OT, nthreads, mskfct); + + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for OT extension:\t\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } + +#ifdef PRINT_OPRG_MASKS + for(i = 0, ctr=0; i < nbins; i++) { + if(nelesinbin[i] > 0) { + cout << "Result for element i = " << i << " and choice = " << (hex) << + choices.Get(i * OTsPerElement*8, OTsPerElement*8) << (dec) << ": "; + for(uint32_t j = 0; j < maskbytelen; j++) { + cout << (hex) << (uint32_t) res_buf[ctr * maskbytelen + j] << (dec); + } + cout << endl; + ctr++; + //resulting_masks[i].PrintHex(); + } + //memcpy(res_buf_ptr, resulting_masks[i].GetArr(), maskbytelen); + } +#endif + + + evaluate_crf(res_buf, res_buf, neles, maskbytelen, crypt); + + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for CRF evaluation:\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + } + + delete mskfct; +} + + + + +void oprg_server(uint8_t* hash_table, uint32_t nbins, uint32_t totaleles, uint32_t* nelesinbin, uint32_t elebitlen, + uint32_t maskbitlen, crypto* crypt, CSocket* sock, uint32_t nthreads, uint8_t* res_buf) { + CBitVector input, results; + CBitVector baseOTchoices; + uint8_t* keySeeds; + uint32_t numOTs, OTsPerElement, i, maskbytelen; + OTExtension1ooNECCSender* sender; + timeval t_start, t_end; + + maskbytelen = maskbitlen / 8; + + OTsPerElement = ceil_divide(elebitlen, 8); + numOTs = nbins * OTsPerElement; + +#ifndef BATCH + cout << "Server: bins = " << nbins << ", elebitlen = " << elebitlen << " and maskbitlen = " << + maskbitlen << " and performs " << numOTs << " OTs" << endl; +#endif + + baseOTchoices.Create(m_nCodeWordBits); + crypt->gen_rnd(baseOTchoices.GetArr(), ceil_divide(m_nCodeWordBits, 8)); + + keySeeds = (uint8_t*) malloc(crypt->get_aes_key_bytes()*m_nCodeWordBits); + + if(DETAILED_TIMINGS) { + gettimeofday(&t_start, NULL); + } + InitOTSender(keySeeds, baseOTchoices, sock[0], crypt); + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for base-OTs:\t\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } + sender = new OTExtension1ooNECCSender(m_nCodeWordBits, crypt, sock, baseOTchoices, keySeeds); + + //Check base-OT seeds + /*for(i = 0; i < m_nCodeWordBits; i++) { + cout << "i = " << i << ": " << (hex) << ((uint64_t*) keySeeds)[(i*2)] << ((uint64_t*) keySeeds)[(i*2)+1] << (dec) << endl; + }*/ + + //for(uint32_t i = 0; i < nbins; i++) { + input.AttachBuf(hash_table, totaleles * ceil_divide(elebitlen, 8)); + results.AttachBuf(res_buf, totaleles * maskbytelen); + //input.Reset(); + results.Reset(); + //} + + CBitVector values[2]; + values[0].Create(numOTs * AES_BITS); + values[1].Create(numOTs * AES_BITS); + + //m_fMaskFct = new XORMasking(bitlength, m_cCrypto); + OPEMasking* mskfct = new OPEMasking(elebitlen, maskbitlen, nbins, nelesinbin, input, results, crypt); + //cout << "Sender performing " << numOTs << " ots" << endl; + sender->send(numOTs, AES_BITS, values, RN_OT, nthreads, mskfct);//ObliviouslySend(values, numOTs, AES_BITS, RN_OT); + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for OT extension:\t\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + gettimeofday(&t_start, NULL); + } + +#ifdef PRINT_OPRG_MASKS + for(i = 0; i < totaleles; i++) { + cout << "Result for element i = " << i << ": "; + for(uint32_t j = 0; j < maskbytelen; j++) { + cout << (hex) << (uint32_t) res_buf[i * maskbytelen + j] << (dec); + } + cout << endl; + } +#endif + //memcpy(res_buf_ptr, results[i].GetArr(), maskbytelen * nelesinbin[i]); + //res_buf_ptr+=maskbytelen * nelesinbin[i]; + + //evaluate correlation robust function on the elements + evaluate_crf(res_buf, res_buf, totaleles, maskbytelen, crypt); + + if(DETAILED_TIMINGS) { + gettimeofday(&t_end, NULL); + cout << "Time for CRF evaluation:\t" << fixed << std::setprecision(2) << + getMillies(t_start, t_end) << " ms" << endl; + } + + delete mskfct; +} + + +void InitOTSender(uint8_t* keySeeds, CBitVector& choices, CSocket sock, crypto* crypt) +{ +#ifdef TIMING + timeval np_begin, np_end; +#endif + +// keySeeds = (uint8_t*) malloc(crypt->get_aes_key_bytes()*m_nCodeWordBits); + NaorPinkas* bot = new NaorPinkas(crypt, ECC_FIELD); + + +#ifdef TIMING + gettimeofday(&np_begin, NULL); +#endif + + uint32_t numbaseOTs = m_nCodeWordBits; + uint8_t* pBuf = (uint8_t*) malloc(numbaseOTs * crypt->get_hash_bytes()); + + bot->Receiver(2, numbaseOTs, choices, sock, pBuf); + + //Key expansion + uint8_t* pBufIdx = pBuf; + for(uint32_t i=0; iget_aes_key_bytes(), pBufIdx, crypt->get_aes_key_bytes()); + pBufIdx+=crypt->get_hash_bytes(); + //cout << i << ": " << (hex) << ((uint64_t*)keySeeds)[2*i] << ((uint64_t*)keySeeds)[2*i+1]<< (dec) << endl; + } + free(pBuf); + +#ifdef TIMING + gettimeofday(&np_end, NULL); + printf("Time for performing the NP base-OTs: %f seconds\n", getMillies(np_begin, np_end)); +#endif + +} + +void InitOTReceiver(uint8_t* keyMtx, CSocket sock, crypto* crypt) +{ +#ifdef TIMING + timeval np_begin, np_end; +#endif + + NaorPinkas* bot = new NaorPinkas(crypt, ECC_FIELD);//NaorPinkas(m_sSecLvl, m_aSeed); + +#ifdef TIMING + gettimeofday(&np_begin, NULL); +#endif + + uint32_t numbaseOTs = m_nCodeWordBits; + // Execute NP receiver routine and obtain the key + uint8_t* pBuf = (uint8_t*) malloc(crypt->get_hash_bytes() * numbaseOTs * 2); + bot->Sender(2, numbaseOTs, sock, pBuf); + + //Key expansion + uint8_t* pBufIdx = pBuf; + for(uint32_t i=0; iget_aes_key_bytes(), pBufIdx, crypt->get_aes_key_bytes()); + pBufIdx += crypt->get_hash_bytes(); + //cout << i/2 << ": " << (hex) << ((uint64_t*)keyMtx)[2*i] << ((uint64_t*)keyMtx)[2*i+1]<< (dec) << endl; + } + + free(pBuf); + + +#ifdef TIMING + gettimeofday(&np_end, NULL); + printf("Time for performing the NP base-OTs: %f seconds\n", getMillies(np_begin, np_end)); +#endif +} + + +void send_masks(uint8_t* masks, uint32_t nmasks, uint32_t maskbytelen, CSocket& sock) { + sock.Send(masks, nmasks*maskbytelen); +} + + +void receive_masks(uint8_t* masks, uint32_t nmasks, uint32_t maskbytelen, CSocket& sock) { + sock.Receive(masks, nmasks*maskbytelen); +} + + +GHashTable* otpsi_create_hash_table(uint32_t elebytelen, uint8_t* hashes, uint32_t neles, uint32_t + hashbytelen, uint32_t* perm) { + uint64_t tmpbuf; + uint32_t i, tmp_hashbytelen; + + tmp_hashbytelen = min((uint32_t) sizeof(uint64_t), hashbytelen); + + GHashTable *map= g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL); + for(i = 0; i < neles; i++) { + memcpy((uint8_t*) &tmpbuf, hashes + i*tmp_hashbytelen, tmp_hashbytelen); + g_hash_table_insert(map,(void*) &tmpbuf, &(perm[i])); + } + return map; +} + + +void *otpsi_query_hash_table(void* ctx_tmp) {//GHashTable *map, uint8_t* elements, uint8_t** result, uint32_t elebytelen, + //uint8_t* qhashes, uint32_t qneles, uint32_t hashbytelen) { + + cout << "Starting to query hash table" << endl; + query_ctx* qctx = (query_ctx*) ctx_tmp; + + uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * qctx->qneles); + uint32_t* tmpval; + GHashTable *map = qctx->map; + uint8_t* qhashes = qctx->qhashes; + uint8_t* elements = qctx->elements; + uint64_t tmpbuf; + + uint32_t size_intersect, i, intersect_ctr, tmp_hashbytelen, elebytelen; + elebytelen = qctx->elebytelen; + + tmp_hashbytelen = min((uint32_t) sizeof(uint64_t), qctx->hashbytelen); + + for(i = 0, intersect_ctr = 0; i < qctx->qneles; i++) { + memcpy((uint8_t*) &tmpbuf, qhashes + i*tmp_hashbytelen, tmp_hashbytelen); + if(g_hash_table_lookup_extended(map, (void*) &tmpbuf, NULL, (void**) &tmpval)) { + matches[intersect_ctr] = tmpval[0]; + intersect_ctr++; + } + } + + size_intersect = intersect_ctr; + + qctx->result = (uint8_t*) malloc(sizeof(uint8_t) * size_intersect * elebytelen); + for(i = 0; i < size_intersect; i++) { + memcpy((qctx->result) + i * elebytelen, elements + matches[i] * elebytelen, elebytelen); + } + qctx->res_size = size_intersect; + + free(matches); + //return size_intersect; +} + +//TODO if this works correctly, combine with other find intersection methods and outsource to hashing_util.h +uint32_t otpsi_find_intersection(uint32_t** result, uint8_t* my_hashes, + uint32_t my_neles, uint8_t* pa_hashes, uint32_t pa_neles, uint32_t hashbytelen, uint32_t* perm) { + uint32_t keys_stored; + uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * my_neles); + uint32_t* tmpval; + uint64_t tmpbuf; + uint32_t* tmpkeys; + + uint32_t size_intersect, i, intersect_ctr, tmp_hashbytelen; + + //tmp_hashbytelen; //= min((uint32_t) sizeof(uint64_t), hashbytelen); + if(sizeof(uint64_t) < hashbytelen) { + keys_stored = 2; + tmp_hashbytelen = sizeof(uint64_t); + tmpkeys = (uint32_t*) calloc(my_neles * keys_stored, sizeof(uint32_t)); + for(i = 0; i < my_neles; i++) { + memcpy(tmpkeys + 2*i, my_hashes + i*hashbytelen + sizeof(uint64_t), hashbytelen-sizeof(uint64_t)); + memcpy(tmpkeys + 2*i + 1, perm + i, sizeof(uint32_t)); + } + } else { + keys_stored = 1; + tmp_hashbytelen = hashbytelen; + tmpkeys = (uint32_t*) malloc(my_neles * keys_stored * sizeof(uint32_t)); + memcpy(tmpkeys, perm, my_neles * sizeof(uint32_t)); + } + + GHashTable *map= g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL); + for(i = 0; i < my_neles; i++) { + //tmpbuf=0; + memcpy((uint8_t*) &tmpbuf, my_hashes + i*hashbytelen, tmp_hashbytelen); + //cout << "Insertion, " << i << " = " <<(hex) << tmpbuf << endl; + //for(uint32_t j = 0; j < tmp_hashbytelen; j++) + + g_hash_table_insert(map,(void*) &tmpbuf, &(tmpkeys[i*keys_stored])); + } + + for(i = 0, intersect_ctr = 0; i < pa_neles; i++) { + //tmpbuf=0; + memcpy((uint8_t*) &tmpbuf, pa_hashes + i*hashbytelen, tmp_hashbytelen); + //cout << "Query, " << i << " = " <<(hex) << tmpbuf << endl; + if(g_hash_table_lookup_extended(map, (void*) &tmpbuf, NULL, (void**) &tmpval)) { + if(keys_stored > 1) { + tmpbuf = 0; + memcpy((uint8_t*) &tmpbuf, pa_hashes + i*hashbytelen+sizeof(uint64_t), hashbytelen-sizeof(uint64_t)); + if((uint32_t) tmpbuf == tmpval[0]) { + matches[intersect_ctr] = tmpval[1]; + if(intersect_ctrinit_aes_key(&aes_key, 128, (uint8_t*) const_seed); + for(i = 0; i < nelements; i++) { + //cout << "Input: " << ((uint64_t*)masks)[0] << endl; + crypt->fixed_key_aes_hash(&aes_key, result+i*elebytelen, elebytelen, masks+i*elebytelen, elebytelen); + //cout << "Input: " << ((uint64_t*)masks)[0] << endl; + } +} + + + +void print_bin_content(uint8_t* hash_table, uint32_t nbins, uint32_t elebytelen, uint32_t* nelesinbin, bool multi_values) { + uint32_t i, j, k, ctr; + if(multi_values) { + for(i = 0, ctr = 0; i < nbins; i++) { + cout << "(" << nelesinbin[i] << ") Bin " << i << ": "; + for(j = 0; j < nelesinbin[i]; j++) { + for(k = 0; k < elebytelen; k++, ctr++) { + cout << (hex) << (unsigned int) hash_table[ctr] << (dec); + } + cout << " "; + } + cout << endl; + } + } else { + for(i = 0, ctr = 0; i < nbins; i++) { + cout << "Bin " << i << ": "; + for(k = 0; k < elebytelen; k++, ctr++) { + cout << (hex) << (unsigned int) hash_table[ctr] << (dec); + } + cout << endl; + } + cout << endl; + } +} + +void *receive_masks(void *ctx_tmp) { + mask_rcv_ctx* ctx = (mask_rcv_ctx*) ctx_tmp; + ctx->sock->Receive(ctx->rcv_buf, ctx->maskbytelen * ctx->nmasks); +} + diff --git a/src/ot-based/ot-psi.h b/src/ot-based/ot-psi.h new file mode 100644 index 0000000..f6cc19c --- /dev/null +++ b/src/ot-based/ot-psi.h @@ -0,0 +1,93 @@ +/* + * ot-psi.h + * + * Created on: Jul 16, 2014 + * Author: mzohner + */ + +#ifndef OT_PSI_H_ +#define OT_PSI_H_ + +#include "../util/typedefs.h" +#include "../util/crypto/crypto.h" +#include "../util/cbitvector.h" +#include "../util/socket.h" +#include "../util/connection.h" +#include "../hashing/cuckoo.h" +#include "../hashing/simple_hashing.h" +#include "../util/ot/ot-extension-1oon-ecc.h" +#include "../util/ot/naor-pinkas.h" +#include "../util/ot/opemasking.h" +#include +#include + +static bool DETAILED_TIMINGS=0; + +//#define DEBUG +//#define PRINT_BIN_CONTENT +//#define PRINT_OPRG_MASKS +//#define PRINT_RECEIVED_VALUES + +struct mask_rcv_ctx { + uint8_t* rcv_buf; + uint32_t nmasks; + uint32_t maskbytelen; + CSocket* sock; +}; + +struct query_ctx { + GHashTable *map; + uint8_t* result; + uint32_t res_size; + + uint8_t* elements; + uint32_t elebytelen; + + uint8_t* qhashes; + uint32_t qneles; + uint32_t hashbytelen; +}; + + +uint32_t otpsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t elebitlen, uint8_t* elements, + uint8_t** result, crypto* crypt_env, CSocket* sock, uint32_t ntasks, double epsilon=1.2, + bool detailed_timings=false); + +uint32_t otpsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t* elebytelens, uint8_t** elements, + uint8_t*** result, uint32_t** res_bytelen, crypto* crypt_env, CSocket* sock, uint32_t ntasks, double epsilon=1.2, + bool detailed_timings=false); + + +uint32_t otpsi_client(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t pneles, uint32_t elebitlen, uint32_t maskbitlen, + crypto* crypt_env, CSocket* sock, uint32_t ntasks, prf_state_ctx* prf_state, uint32_t** result); + +void otpsi_server(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t pneles, uint32_t elebitlen, uint32_t maskbitlen, + crypto* crypt_env, CSocket* sock, uint32_t ntasks, prf_state_ctx* prf_state); + +void oprg_client(uint8_t* hash_table, uint32_t nbins, uint32_t neles, uint32_t* nelesinbin, uint32_t elebitlen, + uint32_t maskbitlen, crypto* crypt, CSocket* sock, uint32_t nthreads, uint8_t* res_buf); +void oprg_server(uint8_t* hash_table, uint32_t nbins, uint32_t totaleles, uint32_t* nelesinbin, uint32_t elebitlen, + uint32_t maskbitlen, crypto* crypt, CSocket* sock, uint32_t nthreads, uint8_t* res_buf); + +void send_masks(uint8_t* masks, uint32_t nmasks, uint32_t maskbytelen, CSocket& sock); +void *receive_masks(void *ctx_tmp); + + +void InitOTReceiver(uint8_t* keyMtx, CSocket sock, crypto* crypt); +void InitOTSender(uint8_t* keySeeds, CBitVector& choices, CSocket sock, crypto* crypt); + +void print_ot_psi_usage(); + +GHashTable* otpsi_create_hash_table(uint32_t elebytelen, uint8_t* hashes, uint32_t neles, uint32_t + hashbytelen, uint32_t* perm); +void *otpsi_query_hash_table(void* ctx_tmp); + +uint32_t otpsi_find_intersection(uint32_t** result, uint8_t* my_hashes, + uint32_t my_neles, uint8_t* pa_hashes, uint32_t pa_neles, uint32_t hashbytelen, uint32_t* perm); + +void print_bin_content(uint8_t* hash_table, uint32_t nbins, uint32_t elebytelen, uint32_t* nelesinbin, bool multi_values); + +void evaluate_crf(uint8_t* result, uint8_t* masks, uint32_t nelements, uint32_t elebytelen, crypto* crypt); + + +#endif /* OT_PSI_H_ */ diff --git a/src/pk-based/dh-psi.cpp b/src/pk-based/dh-psi.cpp new file mode 100644 index 0000000..bab62a5 --- /dev/null +++ b/src/pk-based/dh-psi.cpp @@ -0,0 +1,325 @@ +/* + * dh-psi.cpp + * + * Created on: Jul 9, 2014 + * Author: mzohner + */ +#include "dh-psi.h" + +uint32_t dhpsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t elebytelen, uint8_t* elements, + uint8_t** result, crypto* crypt_env, CSocket* sock, uint32_t ntasks, bool cardinality, field_type ftype) { + + uint32_t i, hash_bytes = crypt_env->get_hash_bytes(), intersect_size, fe_bytes, sndbufsize, rcvbufsize; + task_ctx ectx; + pk_crypto* field = crypt_env->gen_field(ftype); + num* exponent = field->get_rnd_num(); + CSocket* tmpsock = sock; + + fe_bytes = field->fe_byte_size(); + + uint32_t* perm = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint32_t* cardinality_perm; + uint8_t* permeles = (uint8_t*) malloc(sizeof(uint8_t) * neles * elebytelen); + uint8_t* encrypted_eles = (uint8_t*) malloc(sizeof(uint8_t) * neles * fe_bytes); + uint8_t* hashes = (uint8_t*) malloc(sizeof(uint8_t) * neles * hash_bytes); + + //Partner's elements and hashes + uint8_t *peles, *phashes, *perm_peles; + + + /* Permute the elements */ + crypt_env->gen_rnd_perm(perm, neles); + for(i = 0; i < neles; i++) { + memcpy(permeles + perm[i] * elebytelen, elements + i * elebytelen, elebytelen); + } + + /* Hash elements */ + ectx.eles.input = permeles; + ectx.eles.output = hashes; + ectx.eles.nelements = neles; + ectx.eles.inbytelen = elebytelen; + ectx.eles.outbytelen = hash_bytes; + ectx.hctx.symcrypt = crypt_env; + +#ifdef DEBUG + cout << "Hashing elements" << endl; +#endif + run_task(ntasks, ectx, hash); + + /* Encrypt elements */ + ectx.eles.input = hashes; + ectx.eles.inbytelen = hash_bytes; + ectx.eles.nelements = neles; + ectx.eles.outbytelen = fe_bytes; + ectx.eles.output = encrypted_eles; + ectx.ectx.field = field; + ectx.ectx.exponent = exponent; + ectx.ectx.sample = true; + +#ifdef DEBUG + cout << "Hash and encrypting my elements" << endl; +#endif + run_task(ntasks, ectx, encrypt); + + + peles = (uint8_t*) malloc(sizeof(uint8_t) * pneles * fe_bytes); +#ifdef DEBUG + cout << "Exchanging ciphertexts" << endl; +#endif + snd_and_rcv(encrypted_eles, neles * fe_bytes, peles, pneles * fe_bytes, tmpsock); + + + if(cardinality) { + //samle permutation, permute elements, and copy back to original array + cardinality_perm = (uint32_t*) malloc(sizeof(uint32_t) * pneles); + crypt_env->gen_rnd_perm(cardinality_perm, pneles); + perm_peles = (uint8_t*) malloc(pneles * fe_bytes); + for(i = 0; i < pneles; i++) { + memcpy(perm_peles + cardinality_perm[i] * fe_bytes, peles + i * fe_bytes, fe_bytes); + } + memcpy(peles, perm_peles, fe_bytes * pneles); + free(cardinality_perm); + free(perm_peles); + } + + /* Import and Encrypt elements again */ + ectx.eles.input = peles; + ectx.eles.output = peles; + ectx.eles.nelements = pneles; + ectx.eles.inbytelen = fe_bytes; + ectx.eles.outbytelen = fe_bytes; + ectx.ectx.exponent = exponent; + ectx.ectx.sample = false; + +#ifdef DEBUG + cout << "Encrypting partners elements" << endl; +#endif + run_task(ntasks, ectx, encrypt); + + /* Hash elements */ + phashes = (uint8_t*) malloc(sizeof(uint8_t) * pneles * hash_bytes); + + ectx.eles.input = peles; + ectx.eles.output = phashes; + ectx.eles.nelements = pneles; + ectx.eles.inbytelen = fe_bytes; + ectx.eles.outbytelen = hash_bytes; + ectx.hctx.symcrypt = crypt_env; + +#ifdef DEBUG + cout << "Hashing elements" << endl; +#endif + run_task(ntasks, ectx, hash); + +#ifdef DEBUG + cout << "Exchanging hashes" << endl; +#endif + + if(role == SERVER) { + sndbufsize = pneles * hash_bytes; + rcvbufsize = 0; + } else { + sndbufsize = 0; + rcvbufsize = neles * hash_bytes; + } + + snd_and_rcv(phashes, sndbufsize, hashes, rcvbufsize, tmpsock); + +#ifdef DEBUG + cout << "Finding intersection" << endl; +#endif + if(role == SERVER) { + intersect_size = 0; + } else { + intersect_size = find_intersection(elements, result, elebytelen, hashes, + neles, phashes, pneles, hash_bytes, perm); + } + +#ifdef DEBUG + cout << "Free-ing allocated memory" << endl; +#endif + free(perm); + free(permeles); + free(encrypted_eles); + free(hashes); + free(peles); + free(phashes); + + return intersect_size; +} + + + +uint32_t find_intersection(uint8_t* elements, uint8_t** result, uint32_t elebytelen, uint8_t* hashes, + uint32_t neles, uint8_t* phashes, uint32_t npeles, uint32_t hashbytelen, uint32_t* perm) { + + uint32_t* invperm = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint64_t* tmpinbuf; + uint64_t* tmpval; + uint32_t size_intersect, i, intersect_ctr, nextrakeysstored, j; + bool success; + + + nextrakeysstored = ceil_divide(hashbytelen, sizeof(uint64_t))-1; + cout << "hashbytelen = " << hashbytelen << ", nextrakeysstored = " << nextrakeysstored << endl; + + //store all the extra keys as well as the + tmpinbuf = (uint64_t*) malloc(neles * (nextrakeysstored+1) * sizeof(uint64_t)); + + for(i = 0; i < neles; i++) { + memcpy(tmpinbuf + i * (nextrakeysstored+1), hashes + i * hashbytelen + sizeof(uint64_t), + nextrakeysstored*sizeof(uint64_t)); + tmpinbuf[perm[i] * (nextrakeysstored+1) + nextrakeysstored] = (uint64_t) i; + //invperm[perm[i]] = i; + } + + + GHashTable *map= g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL); + for(i = 0; i < neles; i++) { + // g_hash_table_insert(map,(void*) ((uint64_t*) &(hashes[i*hashbytelen])), &(invperm[i])); + g_hash_table_insert(map,(void*) ((uint64_t*) &(hashes[i*hashbytelen])), &(tmpinbuf[i*(nextrakeysstored+1)])); + } + + for(i = 0, intersect_ctr = 0; i < npeles; i++) { + success = true; + if(g_hash_table_lookup_extended(map, (void*) ((uint64_t*) &(phashes[i*hashbytelen])), + NULL, (void**) &tmpval)) { + for(j = 0; j < nextrakeysstored; j++) { + if(((uint64_t*) &(phashes[i*hashbytelen]))[j+1] != tmpval[j]) { + success = false; + } + } + if(success) { + matches[intersect_ctr] = tmpval[nextrakeysstored]; + intersect_ctr++; + } + } + } + + size_intersect = intersect_ctr; + + //result = (uint8_t**) malloc(sizeof(uint8_t*)); + (*result) = (uint8_t*) malloc(sizeof(uint8_t) * size_intersect * elebytelen); + for(i = 0; i < size_intersect; i++) { + memcpy((*result) + i * elebytelen, elements + matches[i] * elebytelen, elebytelen); + } + + free(invperm); + free(matches); + free(tmpinbuf); + return size_intersect; +} + +void snd_and_rcv(uint8_t* snd_buf, uint32_t snd_bytes, uint8_t* rcv_buf, uint32_t rcv_bytes, CSocket* sock) { + pthread_t snd_task; + bool created, joined; + snd_ctx ctx; + + //Start new sender thread + ctx.sock = sock; + ctx.snd_buf = snd_buf; + ctx.snd_bytes = snd_bytes; + created = !pthread_create(&snd_task, NULL, send_data, (void*) &(ctx)); + + //receive + sock->Receive(rcv_buf, rcv_bytes); + assert(created); + + joined = !pthread_join(snd_task, NULL); + assert(joined); + +} + +void run_task(uint32_t nthreads, task_ctx context, void* (*func)(void*) ) { + task_ctx* contexts = (task_ctx*) malloc(sizeof(task_ctx) * nthreads); + pthread_t* threads = (pthread_t*) malloc(sizeof(pthread_t) * nthreads); + uint32_t i, neles_thread, electr, neles_cur; + bool created, joined; + + neles_thread = ceil_divide(context.eles.nelements, nthreads); + for(i = 0, electr = 0; i < nthreads; i++) { + neles_cur = min(context.eles.nelements - electr, neles_thread); + memcpy(contexts + i, &context, sizeof(task_ctx)); + contexts[i].eles.nelements = neles_cur; + contexts[i].eles.input = context.eles.input + (context.eles.inbytelen * electr); + contexts[i].eles.output = context.eles.output + (context.eles.outbytelen * electr); + electr += neles_cur; + } + + for(i = 0; i < nthreads; i++) { + created = !pthread_create(threads + i, NULL, func, (void*) &(contexts[i])); + } + + assert(created); + + for(i = 0; i < nthreads; i++) { + joined = !pthread_join(threads[i], NULL); + } + + assert(joined); + + free(threads); + free(contexts); +} + + +void *encrypt(void* context) { +#ifdef DEBUG + cout << "Encryption task started" << endl; +#endif + pk_crypto* field = ((task_ctx*) context)->ectx.field; + element_ctx electx = ((task_ctx*) context)->eles; + num* e = ((task_ctx*) context)->ectx.exponent; + fe* tmpfe = field->get_fe(); + uint8_t *inptr=electx.input, *outptr=electx.output; + uint32_t i; + + + for(i = 0; i < electx.nelements; i++, inptr+=electx.inbytelen, outptr+=electx.outbytelen) { + if(((task_ctx*) context)->ectx.sample) { + tmpfe->sample_fe_from_bytes(inptr, electx.inbytelen); + //cout << "Mapped " << ((uint32_t*) inptr)[0] << " to "; + } else { + tmpfe->import_from_bytes(inptr); + } + tmpfe->set_pow(tmpfe, e); + //tmpfe->print(); + tmpfe->export_to_bytes(outptr); + } + + return 0; +} + +void *hash(void* context) { +#ifdef DEBUG + cout << "Hashing thread started" << endl; +#endif + crypto* crypt_env = ((task_ctx*) context)->hctx.symcrypt; + element_ctx electx = ((task_ctx*) context)->eles; + + uint8_t *inptr=electx.input, *outptr=electx.output; + uint32_t i; + + + for(i = 0; i < electx.nelements; i++, inptr+=electx.inbytelen, outptr+=electx.outbytelen) { + crypt_env->hash(outptr, electx.outbytelen, inptr, electx.inbytelen); + } + return 0; +} + +void *send_data(void* context) { + snd_ctx *ctx = (snd_ctx*) context; + ctx->sock->Send(ctx->snd_buf, ctx->snd_bytes); + return 0; +} + + + + +void print_dh_psi_usage() { + cout << "Usage: ./dhpsi [0 (server)/1 (client)] [num_elements] " << + "[element_byte_length] [sym_security_bits] [server_ip] [server_port]" << endl; + cout << "Program exiting" << endl; + exit(0); +} diff --git a/src/pk-based/dh-psi.h b/src/pk-based/dh-psi.h new file mode 100644 index 0000000..949171c --- /dev/null +++ b/src/pk-based/dh-psi.h @@ -0,0 +1,69 @@ +/* + * dh-psi.h + * + * Created on: Jul 9, 2014 + * Author: mzohner + */ + +#ifndef DH_PSI_H_ +#define DH_PSI_H_ + + +#include "../util/typedefs.h" +#include "../util/connection.h" +#include "../util/crypto/crypto.h" +#include "../util/crypto/pk-crypto.h" +#include + + +struct element_ctx { + uint32_t nelements; + uint32_t inbytelen; + uint8_t* input; + uint32_t outbytelen; + uint8_t* output; +}; + +struct encrypt_ctx { + num* exponent; + pk_crypto* field; + bool sample; +}; + +struct hash_ctx { + crypto* symcrypt; +}; + +struct task_ctx { + element_ctx eles; + union { + hash_ctx hctx; + encrypt_ctx ectx; + }; +}; + +struct snd_ctx { + uint8_t* snd_buf; + uint32_t snd_bytes; + CSocket* sock; +}; + + +void print_dh_psi_usage(); +uint32_t dhpsi(role_type role, uint32_t neles, uint32_t pneles, uint32_t elebytelen, uint8_t* elements, + uint8_t** result, crypto* crypt_env, CSocket* sock, uint32_t ntasks, bool cardinality=false, + field_type ftype=ECC_FIELD); +void run_task(uint32_t nthreads, task_ctx context, void* (*func)(void*) ); +void permute(uint32_t nelements, uint32_t bytelen, uint8_t* elements, uint8_t* result, uint32_t* perm); +uint32_t find_intersection(uint8_t* elements, uint8_t** result, uint32_t elebytelen, uint8_t* hashes, + uint32_t neles, uint8_t* phashes, uint32_t peles, uint32_t hashbytelen, uint32_t* perm); +void snd_and_rcv(uint8_t* snd_buf, uint32_t snd_bytes, uint8_t* rcv_buf, uint32_t rcv_bytes, CSocket* sock); +void *encrypt(void* context); +void *hash(void* context); +void *send_data(void* context); + + + + + +#endif /* DH_PSI_H_ */ diff --git a/src/thirdparty/shpsi.cpp b/src/thirdparty/shpsi.cpp new file mode 100644 index 0000000..a813444 --- /dev/null +++ b/src/thirdparty/shpsi.cpp @@ -0,0 +1,329 @@ +#include "shpsi.h" + + + +/*int32_t main(int32_t argc, char** argv) { + uint32_t pid, nclients, nelements, elebytelen, symsecbits; + uint8_t *elements, *intersection; + const char* address; + uint16_t port; + timeval begin, end; + + if(argc < 2) { + print_sh_psi_usage(); + } else { + pid = atoi(argv[1]); + if((pid == 0 && argc < 5) || (pid > 0 && argc < 6)) print_sh_psi_usage(); + } + + if(pid == 0) { // Play as server + nclients = atoi(argv[2]); + address = argv[3]; + port = (uint16_t) atoi(argv[4]); + server_routine(nclients, address, port); + } else { // Play as client + nelements = atoi(argv[2]); + elebytelen = atoi(argv[3]); + symsecbits = atoi(argv[4]); + address = argv[5]; + port = atoi(argv[6]); + elements = (uint8_t*) malloc(sizeof(uint8_t) * elebytelen * nelements); + crypto crypto(symsecbits); + crypto.gen_rnd(elements, elebytelen * nelements); + +#ifdef DEBUG + //Load some dummy-values + for(uint32_t i = 0; i < nelements; i++) { + ((uint32_t*) elements)[i] = i+(nelements/pid); + } +#endif + gettimeofday(&begin, NULL); + client_routine(nelements, elebytelen, elements, &intersection, symsecbits, address, port); + gettimeofday(&end, NULL); + cout << "Computing the intersection took " << getMillies(begin, end) << " ms" << endl; + } + cout << "Program execution finished" << endl; + return 0; +}*/ + +void server_routine(uint32_t nclients, CSocket* socket, bool cardinality) { + //cout << "Starting server for " << nclients << " clients on address " << address << ":" << port << endl; + + CSocket* sockfds = socket;//(CSocket*) malloc(sizeof(CSocket) * nclients); + uint32_t* neles = (uint32_t*) malloc(sizeof(uint32_t) * nclients); + uint8_t** csets = (uint8_t**) malloc(sizeof(uint8_t*) * nclients); + uint8_t* intersect; + uint32_t temp, maskbytelen, intersectsize, minset, i; + +#ifndef BATCH + cout << "Connections with all " << nclients << " clients established" << endl; +#endif + + /* Receive the input sizes and bit lengths for all clients */ + for(i = 0; i < nclients; i++) { + sockfds[i].Receive(neles+i, sizeof(uint32_t)); + sockfds[i].Receive(&temp, sizeof(uint32_t)); + if(i == 0) { maskbytelen = temp; minset = neles[i];} + if(neles[i] < minset) minset = neles[i]; + assert(maskbytelen == temp); +#ifndef BATCH + cout << "Client " << i << " holds " << neles[i] << " elements of length " << (temp * 8) << "-bit" << endl; +#endif + } +#ifndef BATCH + cout <<"Receiving the client's elements" << endl; +#endif + /* Allocate sufficient size for the intersecting elements */ + intersect = (uint8_t*) malloc(sizeof(uint8_t*) * minset * maskbytelen); + + /* Receive the permuted and masked sets of all clients */ + for(i = 0; i < nclients; i++) { + temp = sizeof(uint8_t) * neles[i] * maskbytelen; + csets[i] = (uint8_t*) malloc(temp); + sockfds[i].Receive(csets[i], temp); + } +#ifndef BATCH + cout << "Computing intersection for the clients" << endl; +#endif + /* Compute Intersection */ + intersectsize = compute_intersection(nclients, neles, csets, intersect, maskbytelen); +#ifndef BATCH + cout << "sending all " << intersectsize << " intersecting elements to the clients" << endl; +#endif + /* Send the intersection size and intersecting elements to all clients */ + for(i = 0; i < nclients; i++) { + sockfds[i].Send(&intersectsize, sizeof(uint32_t)); + if(!cardinality) + sockfds[i].Send(intersect, intersectsize * maskbytelen); + } + + /* Cleanup */ + free(neles); +} + +/* + * compute the intersection using a hash table - is optimized for the two-party case, + * for the n-party case a BF-based approach makes more sense. + */ +//TODO currently only works for 128 bit masks +uint32_t compute_intersection(uint32_t nclients, uint32_t* neles, uint8_t** csets, uint8_t* intersect, uint32_t entrybytelen) { + // Create the GHashTable + GHashTable *map = NULL, *tmpmap = NULL; + GHashTableIter iter; + timeval begin, end; + + map = g_hash_table_new_full( + g_int64_hash, g_int64_equal, + NULL, // no cleanup for key + NULL // cleanup value + ); + + uint32_t i, j, intersectsize, ctr = 0; + uint64_t* tmpval = (uint64_t*) malloc(sizeof(uint64_t)); + uint64_t* tmpkey = (uint64_t*) malloc(sizeof(uint64_t)); +#ifndef BATCH + cout << "Inserting the items into the hash table " << endl; +#endif + gettimeofday(&begin, NULL); + for(i=0;iSend((uint8_t*) &neles, sizeof(uint32_t)); + sockfd->Send((uint8_t*) &maskbytelen, sizeof(uint32_t)); + + + perm = mask_and_permute_elements(neles, elebytelen, elements, maskbytelen, masks, crypt->get_seclvl().symbits, crypt); + + sockfd->Send(masks, maskbytelen * neles); + + if(!cardinality) { + for(i = 0; i < neles; i++) { + invperm[perm[i]] = i; + } + + map= g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL); + for(i = 0; i < neles; i++) { + g_hash_table_insert(map,(void*) &((uint64_t*)masks)[2*i], &(invperm[i])); + } + } + + + sockfd->Receive(&intersectsize, sizeof(uint32_t)); + if(!cardinality) { + sockfd->Receive(intersect, maskbytelen * intersectsize); + +#ifdef DEBUG + cout << "The intersection contains " << intersectsize << " elements: " << endl; + for(i = 0; i < intersectsize; i++) { + cout << (hex) << ((uint64_t*)intersect)[2*i] << " " << ((uint64_t*)intersect)[2*i+1] << (dec) << endl; + } +#endif + + *result = (uint8_t*) malloc(elebytelen * intersectsize); + //uint8_t* tmpbuf = (uint8_t*) malloc(maskbytelen); + for(i = 0; i < intersectsize; i++) { + g_hash_table_lookup_extended(map, (void*) &(((uint64_t*)intersect)[2*i]), NULL, (void**) &tmpval); + memcpy((*result) + i * elebytelen, elements + tmpval[0] * elebytelen, elebytelen); + //crypto.decrypt(tmpbuf, intersect+i*maskbytelen, maskbytelen); + //memcpy((*result) + i * elebytelen, tmpbuf, elebytelen); +#ifdef DEBUG + cout << ((uint32_t*) elements)[tmpval[0]] << ", "; +#endif + } +#ifdef DEBUG + cout << endl; +#endif + } + + free(perm); + free(invperm); + + return intersectsize; +} + + +void printKeyValue( gpointer key, gpointer value, gpointer userData ) { + uint64_t realKey = *((uint64_t*)key); + uint64_t realValue = *((uint64_t*)value); + + cout << (hex) << realKey << ": " << realValue << (dec) << endl; + return; +} + +uint32_t* mask_and_permute_elements(uint32_t neles, uint32_t elebytelen, uint8_t* + elements, uint32_t maskbytelen, uint8_t* masks, uint32_t symsecbits, crypto* crypto) { + uint32_t* perm = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint8_t* maskpermptr; + uint32_t i; + + //Get random permutation + crypto->gen_rnd_perm(perm, neles); + //crypto->seed_aes_enc(client_psk); + + //Hash and permute all elements + for(i = 0; i < neles; i++) { + //cout << "Performing encryption for " << i << "-th element " << ((uint32_t*) elements)[i] << ": "; + maskpermptr = masks + perm[i] * maskbytelen; + crypto->hash(maskpermptr, maskbytelen, elements + i * elebytelen, elebytelen); + //crypto->encrypt(maskpermptr, elements+i*elebytelen, elebytelen); + //cout <<(hex)<< ((uint64_t*) maskpermptr)[0] << ((uint64_t*) maskpermptr)[1] << (dec) << endl; +#ifdef DEBUG + cout << "Resulting hash for element " << ((uint32_t*)elements)[i] << ": " << (hex) << ((uint64_t*) maskpermptr)[0] << + " " << ((uint64_t*) maskpermptr)[1] << (dec) << endl; +#endif + } + + + //free(perm); + return perm; +} + +uint32_t ttppsi(role_type role, uint32_t neles, uint32_t elebytelen, uint8_t* elements, + uint8_t** intersection, crypto* crypt, CSocket* sockets, uint32_t nclients, bool cardinality) { + + if(role == 0) { //Start the server + //TODO maybe rerun infinitely + server_routine(nclients, sockets, cardinality); + return 0; + } else { //Start clients + return client_routine(neles, elebytelen, elements, intersection, crypt, sockets, cardinality); + } +} diff --git a/src/thirdparty/shpsi.exe b/src/thirdparty/shpsi.exe new file mode 100755 index 0000000..2674539 Binary files /dev/null and b/src/thirdparty/shpsi.exe differ diff --git a/src/thirdparty/shpsi.h b/src/thirdparty/shpsi.h new file mode 100644 index 0000000..6d36343 --- /dev/null +++ b/src/thirdparty/shpsi.h @@ -0,0 +1,55 @@ +/* + * shpsi.h + * + * Created on: Jul 1, 2014 + * Author: mzohner + */ + +#ifndef SHPSI_H_ +#define SHPSI_H_ + +#include +#include "../util/crypto/crypto.h" +#include "../util/socket.h" +#include "../util/typedefs.h" +#include "../util/connection.h" + + + +/* start both roles*/ +uint32_t ttppsi(role_type role, uint32_t neles, uint32_t elebytelen, uint8_t* elements, + uint8_t** intersection, crypto* crypt, CSocket* socket, uint32_t nclients = 0, bool cardinality=false); + +/* + * Params: + * neles: number of elements in the clients' set + * elebytelen: bytelength of the elements + * elements: byte pointer to the client's set + * intersection: a byte array that holds the intersection upon returning + * address: address of the server + * port: port that the server is listening on + * return: number of intersecting elements + */ +uint32_t client_routine(uint32_t neles, uint32_t elebytelen, uint8_t* elements, + uint8_t** intersection, crypto* crypt, CSocket* socket, bool cardinality); + +/* + * Mask and permute the elements using the pre-shared key + */ +uint32_t* mask_and_permute_elements(uint32_t neles, uint32_t elebytelen, uint8_t* + elements, uint32_t maskbytelen, uint8_t* masks, uint32_t symsecbits, crypto* crypto); + + +/* + * Params: + * nclients: number of participating clients + * address: address of the server + * port: port that the server is listening on + */ +void server_routine(uint32_t nclients, CSocket* socket, bool cardinality); + +uint32_t compute_intersection(uint32_t nclients, uint32_t* neles, uint8_t** csets, uint8_t* intersect, uint32_t entrybytelen); + +void printKeyValue( gpointer key, gpointer value, gpointer userData ); + +#endif /* SHPSI_H_ */ diff --git a/src/util/cbitvector.cpp b/src/util/cbitvector.cpp new file mode 100644 index 0000000..338954a --- /dev/null +++ b/src/util/cbitvector.cpp @@ -0,0 +1,680 @@ +/* +* BitVector.cpp +* +* Created on: May 6, 2013 +* Author: mzohner +*/ + +#include "cbitvector.h" + +/* Fill the bitvector with random values and pre-initialize the key to the seed-key*/ +void CBitVector::FillRand(int bits, crypto* crypt) +{ + InitRand(crypt); + FillRand(bits); +} + +/* Fill random values using the pre-defined AES key */ +void CBitVector::FillRand(int bits) +{ + if(bits > m_nByteSize<<3) + Create(bits); + + /*uint8_t buf[AES_BYTES]; + memset(buf, 0, AES_BYTES); + + for(int i = 0; i < (int) sizeof(int); i++) { + buf[i] = (cnt>>(8*i)) & 0xFF; + }*/ + + if(m_cCrypto== NULL) + { + cerr << "FillRand called without initializing AES key" << endl; + return; + } + + //int size = ceil_divide(bits, AES_BITS); + //unsigned long long* counter = (unsigned long long*) buf; + + m_cCrypto->gen_rnd(m_pBits, (bits>>3)); + + /*for(int i = 0; i < size; i++, counter[0]++, cnt++) + { + MPC_AES_ENCRYPT(m_nKey, m_pBits + i*AES_BYTES, buf); + }*/ + //cnt = (int) counter[0]; +} + +void CBitVector::Create(int numelements, int elementlength, crypto* crypt) +{ + CreateRand(numelements * elementlength, crypt); + m_nElementLength = elementlength; + m_nNumElements = numelements; + m_nNumElementsDimB = 1; +} + +void CBitVector::CreateRand(int bits, crypto* crypt) +{ + FillRand(bits, crypt); +} + +void CBitVector::Create(int bits) +{ + if(bits == 0) bits = DEFAULT_BITSIZE; + //cout << "creating " << bits << " sized vector" << endl; + if(m_nByteSize > 0 ) free(m_pBits); + m_nByteSize = ceil_divide(bits, 8); + m_pBits = (uint8_t*) calloc(m_nByteSize, sizeof(uint8_t));// * m_nSize); + //m_pBits = (uint8_t*) malloc(m_nSize * sizeof(uint8_t));// * m_nSize); + if(m_pBits==NULL) + { + cerr << "CBitVector: memory allocation not successful, requested " << m_nByteSize << " bytes" << endl; + exit(0); + } + m_nElementLength = 1; + m_nNumElements = m_nByteSize; + m_nNumElementsDimB = 1; + +} + +void CBitVector::Create(int numelements, int elementlength) +{ + Create(numelements * elementlength); + m_nElementLength = elementlength; + m_nNumElements = numelements; + m_nNumElementsDimB = 1; +} + +void CBitVector::Create(int numelementsDimA, int numelementsDimB, int elementlength) +{ + Create(numelementsDimA * numelementsDimB * elementlength); + m_nElementLength = elementlength; + m_nNumElements = numelementsDimA; + m_nNumElementsDimB = numelementsDimB; +} +void CBitVector::Create(int numelementsDimA, int numelementsDimB, int elementlength, crypto* crypt) +{ + CreateRand(numelementsDimA * numelementsDimB * elementlength, crypt); + m_nElementLength = elementlength; + m_nNumElements = numelementsDimA; + m_nNumElementsDimB = numelementsDimB; +} + + +void CBitVector::ResizeinBytes(int newSizeBytes) +{ + uint8_t* tBits = m_pBits; + int tSize = m_nByteSize; + + m_nByteSize = newSizeBytes; + m_pBits = new uint8_t[m_nByteSize]; + + memcpy(m_pBits, tBits, tSize); + + delete(tBits); +} + +void CBitVector::Copy(uint8_t* p, int pos, int len) +{ +//#ifdef ASSERT + if( pos+len > m_nByteSize) + { + if(m_pBits) + ResizeinBytes(pos+len); + else + { + CreateBytes(pos+len); + } + } +//#endif + memcpy (m_pBits+pos, p, len); +} + +//pos and len in bits +void CBitVector::SetBits(uint8_t* p, int pos, int len) +{ + + if(len < 1 || (pos+len) > (m_nByteSize << 3)) + return; + + if(len == 1) + { + SetBitNoMask(pos, *p); + return; + } + if(!((pos & 0x07) || (len & 0x07))) + { + + SetBytes(p, pos>>3, len>>3); + return; + } + int posctr = pos>>3; + int lowermask = pos & 7; + int uppermask = 8 - lowermask; + + int i; + uint8_t temp; + for(i = 0; i < len / (sizeof(uint8_t)*8); i++, posctr++) + { + temp = p[i]; + m_pBits[posctr] = (m_pBits[posctr] & RESET_BIT_POSITIONS[lowermask]) | ((temp << lowermask) & 0xFF); + m_pBits[posctr+1] = (m_pBits[posctr+1] & RESET_BIT_POSITIONS_INV[uppermask]) | (temp >> uppermask); + //cout << "Iteration for whole byte done" << endl; + } + int remlen = len & 0x07; + if(remlen) + { + temp = p[i] & RESET_BIT_POSITIONS[remlen]; + //cout << "temp = " << (unsigned int) temp << endl; + if(remlen <= uppermask) + { + //cout << "Setting " << remlen << " lower bits with lowermask = " << lowermask << ", and temp " << (unsigned int) temp << endl; + m_pBits[posctr] = (m_pBits[posctr] & (~(((1<> lowermask) & 0xFF; + //cout << "p[i] = " << (unsigned int) p[i] << endl; + } + else + { + //cout << "Getting upper" << endl; + //cout << "Getting " << remlen << " upper bits with lowermask = " << lowermask << ", " << (unsigned int) m_pBits[posctr] << ", and uppermask = " + // << uppermask << ", " << (unsigned int) m_pBits[posctr+1] << endl; + p[i] = ((m_pBits[posctr] & GET_BIT_POSITIONS[lowermask]) >> lowermask) & 0xFF; + p[i] |= (m_pBits[posctr+1] & (((1<<(remlen-uppermask))-1))) << uppermask; + //cout << "p[i] = " << (unsigned int) p[i] << endl; + } + } +} + +void CBitVector::XORBytesReverse(uint8_t* p, int pos, int len) +{ + uint8_t* src = p; + uint8_t* dst = m_pBits+pos; + uint8_t* lim = dst + len; + while(dst != lim) + { + *dst++ ^= REVERSE_BYTE_ORDER[*src++]; + } +} + +//XOR bits given an offset on the bits for p which is not necessarily divisible by 8 +void CBitVector::XORBitsPosOffset(uint8_t* p, int ppos, int pos, int len) +{ + for(int i = pos, j = ppos; j < ppos + len; i++, j++) + { + m_pBits[i/8] ^= (((p[j/8] & (1 << (j%8))) >> j % 8) << i % 8); + } +} + +void CBitVector::XORBits(uint8_t* p, int pos, int len) { + XORBits(p, (uint64_t) pos, (uint64_t) len); +} + +void CBitVector::XORBits(uint8_t* p, uint64_t pos, uint64_t len) +{ + if(len < 1 || (pos+len) > ((uint64_t) m_nByteSize) << 3) + { + //cout << "m_nSize = " << m_nSize << ", pos+len = " << (pos + len)/8 << endl; + return; + } + if(len == 1) + { + XORBitNoMask(pos, *p); + return; + } + if(!((pos & 0x07) || (len & 0x07))) + { + XORBytes(p, pos>>3, len>>3); + return; + } + uint64_t posctr = pos>>3; + uint64_t lowermask = pos & 7; + uint64_t uppermask = 8 - lowermask; + + uint64_t i; + uint8_t temp; + for(i = 0; i < len / (sizeof(uint8_t)*8); i++, posctr++) + { + temp = p[i]; + m_pBits[posctr] ^= ((temp << lowermask) & 0xFF); + m_pBits[posctr+1] ^= (temp >> uppermask); + //cout << "Iteration for whole byte done" << endl; + } + uint64_t remlen = len & 0x07; + if(remlen) + { + temp = p[i] & RESET_BIT_POSITIONS[remlen]; + //cout << "temp = " << (unsigned int) temp << endl; + if(remlen <= uppermask) + { + //cout << "Setting " << remlen << " lower bits with lowermask = " << lowermask << ", and temp " << (unsigned int) temp << endl; + m_pBits[posctr] ^= ((temp << lowermask) & 0xFF); + } + else + { + //cout << "Setting " << remlen << " bits with lowermask = " << lowermask << ", uppermask = " << uppermask << ", and temp = " << (unsigned int) temp << endl; + m_pBits[posctr] ^= ((temp << lowermask) & 0xFF); + m_pBits[posctr+1] ^= (temp >> uppermask); + } + } +} + +void CBitVector::ORByte(int pos, uint8_t p) +{ + m_pBits[pos] |= p; +} + + +//optimized bytewise for set operation +void CBitVector::GetBytes(uint8_t* p, uint64_t pos, uint64_t len) +{ + + uint8_t* src = m_pBits + pos; + uint8_t* dst = p; + //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations + GetBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst ) + (len>>SHIFTVAL)); + dst += ((len >> SHIFTVAL) << SHIFTVAL); + src += ((len >> SHIFTVAL) << SHIFTVAL); + GetBytes(dst, src, dst+(len & ((1< void CBitVector::GetBytes(T* dst, T* src, T* lim) +{ + while(dst != lim) + { + *dst++ = *src++; + } +} + +void CBitVector::XORBytes(uint8_t* p, uint64_t pos, uint64_t len) +{ + if((pos + len) > (uint64_t) m_nByteSize) { + cerr << "Error Trying to xor at byte position: " << pos << " with len = " << len << " with m_nSize = " << m_nByteSize << endl; + exit(0); + } + + uint8_t* dst = m_pBits + pos; + uint8_t* src = p; + //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations + XORBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst ) + (len>>SHIFTVAL)); + dst += ((len >> SHIFTVAL) << SHIFTVAL); + src += ((len >> SHIFTVAL) << SHIFTVAL); + XORBytes(dst, src, dst+(len & ((1< void CBitVector::XORBytes(T* dst, T* src, T* lim) +{ + while(dst != lim) + { + *dst++ ^= *src++; + } +} + +void CBitVector::XORRepeat(uint8_t* p, int pos, int len, int num) +{ + unsigned short* dst = (unsigned short*) (m_pBits + pos); + unsigned short* src = (unsigned short*) p; + unsigned short* lim = (unsigned short*) (m_pBits+pos+len); + for(int i = num; dst != lim; ) + { + *dst++ ^= *src++; + if(!(--i)) + { + src = (unsigned short*) p; + i = num; + } + } +} + +//optimized bytewise for set operation +void CBitVector::SetBytes(uint8_t* p, int pos, int len) +{ + + uint8_t* dst = m_pBits + pos; + uint8_t* src = p; + //REGSIZE rem = SHIFTVAL-1; + //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations + SetBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst ) + (len>>SHIFTVAL)); + dst += ((len >> SHIFTVAL) << SHIFTVAL); + src += ((len >> SHIFTVAL) << SHIFTVAL); + SetBytes(dst, src, dst+(len & ((1< void CBitVector::SetBytes(T* dst, T* src, T* lim) +{ + while(dst != lim) + { + *dst++ = *src++; + } +} + +//optimized bytewise for AND operation +void CBitVector::ANDBytes(uint8_t* p, int pos, int len) +{ + + uint8_t* dst = m_pBits + pos; + uint8_t* src = p; + //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations + ANDBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst ) + (len>>SHIFTVAL)); + dst += ((len >> SHIFTVAL) << SHIFTVAL); + src += ((len >> SHIFTVAL) << SHIFTVAL); + ANDBytes(dst, src, dst+(len & ((1< void CBitVector::ANDBytes(T* dst, T* src, T* lim) +{ + while(dst != lim) + { + *dst++ &= *src++; + } +} + +void CBitVector::SetXOR(uint8_t* p, uint8_t* q, int pos, int len) +{ + Copy(p, pos, len); + XORBytes(q, pos, len); +} + +void CBitVector::SetAND(uint8_t* p, uint8_t* q, int pos, int len) +{ + Copy(p, pos, len); + ANDBytes(q, pos, len); +} + +void CBitVector:: Print(int fromBit, int toBit) { + int to = toBit > (m_nByteSize << 3)? (m_nByteSize << 3) : toBit; + for (int i = fromBit; i < to; i++) { + cout << (unsigned int) GetBitNoMask(i); + } + cout << endl; +} + +void CBitVector::PrintHex(int fromByte, int toByte) { + for (int i = fromByte; i < toByte; i++) { + cout << setw(2) << setfill('0') << (hex) << ((unsigned int) m_pBits[i]); + } + cout << (dec) << endl; +} + +void CBitVector::PrintHex() +{ + for (int i = 0; i < m_nByteSize; i++) + { + cout << setw(2) << setfill('0') << (hex) << ((unsigned int) m_pBits[i]); + } + cout << (dec) << endl; +} + +void CBitVector::PrintBinaryMasked(int from, int to) +{ + for (int i = from; i < to; i++) + { + cout << (unsigned int) GetBit(i); + } + cout << endl; +} + +void CBitVector::PrintContent() +{ + if(m_nElementLength == 1) + { + PrintHex(); + return; + } + if(m_nNumElementsDimB == 1) + { + for(int i = 0; i < m_nNumElements; i++) + { + cout << Get(i) << ", "; + } + cout << endl; + } + else + { + for(int i = 0; i < m_nNumElements; i++) + { + cout << "("; + for(int j = 0; j < m_nNumElementsDimB-1; j++) + { + cout << Get2D(i, j) << ", "; + } + cout << Get2D(i, m_nNumElementsDimB-1); + cout << "), "; + } + cout << endl; + } +} + + +BOOL CBitVector::IsEqual(CBitVector& vec) +{ + if(vec.GetSize() != m_nByteSize) + return false; + + uint8_t* ptr = vec.GetArr(); + for(int i = 0; i < m_nByteSize; i++) + { + if(ptr[i] != m_pBits[i]) + return false; + } + return true; +} + +BOOL CBitVector::IsEqual(CBitVector& vec, int from, int to) +{ + if(vec.GetSize() * 8 < to || m_nByteSize * 8 < to || from > to) + return false; + + for(int i = from; i < to; i++) { + if(vec.GetBit(i) != GetBit(i) ) + return false; + } + return true; +} + +void CBitVector::XOR_no_mask(int p, int bitPos, int bitLen) +{ + if(!bitLen) + return; + + int i = bitPos>>3, j = 8-(bitPos&0x7), k; + + m_pBits[i++] ^= (GetIntBitsFromLen(p, 0, min(j, bitLen))<<(8-j)) & 0xFF; + + for (k=bitLen-j; k > 0; k-=8, i++, j+=8) + { + m_pBits[i] ^= GetIntBitsFromLen(p, j, min(8, k)); + } +} + + +unsigned int CBitVector::GetInt(int bitPos, int bitLen) +{ + int ret = 0, i = bitPos>>3, j = (bitPos&0x7), k; + ret = (m_pBits[i++] >> (j)) & (GetMask(min(8, bitLen))); + if (bitLen == 1) + return ret; + //cout << "MpBits: " << (unsigned int) m_pBits[i-1] << ", ret: " << ret << endl; + j = 8-j; + for(k = bitLen - j; i<(bitPos + bitLen+7)/8-1; i++, j+=8, k-=8) + { + //ret |= REVERSE_BYTE_ORDER[m_pBits[i+pos]] << (i*8); + ret |= m_pBits[i] << j; + //cout << "MpBits: " <<(unsigned int) m_pBits[i] << ", ret: " << ret << ", j: " << j << endl; + //m_pBits[i+pos] = ( ((REVERSE_NIBBLE_ORDER[(p>>((2*i)*4))&0xF] << 4) | REVERSE_NIBBLE_ORDER[(p>>((2*i+1)*4))&0xF]) & 0xFF);//((p>>((2*i+1)*4))&0xF) | ((p>>((2*i)*4))&0xF) & 0xFF; + } + ret |= (m_pBits[i] & SELECT_BIT_POSITIONS[k]) << j; //for the last execution 0<=k<=8 + //cout << "MpBits: " <<(unsigned int) m_pBits[i] << ", ret: " << ret << ", k = " << k << ", selects: " << (unsigned int) SELECT_BIT_POSITIONS[k] << ", j: " << j << endl; + return ret; +} + +void CBitVector::SimpleTranspose(int rows, int columns) +{ + CBitVector temp(rows * columns); + temp.Copy(m_pBits, 0, rows * columns / 8); + for(int i = 0; i < rows; i++) + { + for(int j = 0; j < columns; j++) + { + SetBit(j * rows + i, temp.GetBit(i * columns + j)); + } + } +} + + +//A transposition algorithm for bit-matrices of size 2^i x 2^i +void CBitVector::EklundhBitTranspose(int rows, int columns) +{ + REGISTER_SIZE* rowaptr;//ptr; + REGISTER_SIZE* rowbptr; + REGISTER_SIZE temp_row; + REGISTER_SIZE mask; + REGISTER_SIZE invmask; + REGISTER_SIZE* lim; + + lim = (REGISTER_SIZE*) m_pBits + ceil_divide(rows * columns, 8); + + int offset = (columns >> 3) / sizeof(REGISTER_SIZE); + int numiters = ceil_log2(rows); + int srcidx = 1, destidx; + int rounds; + int p; + + //If swapping is performed on bit-level + for(int i = 0, j; i < LOG2_REGISTER_SIZE; i++, srcidx*=2) + { + destidx = offset*srcidx; + rowaptr = (REGISTER_SIZE*) m_pBits; + rowbptr = rowaptr + destidx;//ptr = temp_mat; + + //cout << "numrounds = " << numrounds << " iterations: " << LOG2_REGISTER_SIZE << ", offset = " << offset << ", srcidx = " << srcidx << ", destidx = " << destidx << endl; + //Preset the masks that are required for bit-level swapping operations + mask = TRANSPOSITION_MASKS[i]; + invmask = ~mask; + + //If swapping is performed on byte-level reverse operations due to little-endian format. + rounds = rows / (srcidx * 2); + if(i > 2) { + for(int j = 0; j < rounds; j++) { + for(lim = rowbptr+destidx;rowbptr < lim; rowaptr++, rowbptr++) { + temp_row = *rowaptr; + *rowaptr = ((*rowaptr & mask) ^ ((*rowbptr & mask)<>srcidx)); + } + rowaptr+=destidx; + rowbptr+=destidx; + } + } + else { + for(int j = 0; j < rounds; j++) { + for(lim = rowbptr+destidx;rowbptr < lim; rowaptr++, rowbptr++) { + temp_row = *rowaptr; + *rowaptr = ((*rowaptr & invmask) ^ ((*rowbptr & invmask)>>srcidx)); + *rowbptr = ((*rowbptr & mask) ^ ((temp_row & mask)<= swapoffset)) { + temp_row = *rowaptr; + *rowaptr = *rowbptr; + *rowbptr = temp_row; + } + } + rowaptr+=destidx; + rowbptr+=destidx; + } + } + + if(columns > rows) { + uint8_t* tempvec = (uint8_t*) malloc((rows*columns)/8); + memcpy(tempvec, m_pBits, ((rows/8)*columns)); + + rowaptr = (REGISTER_SIZE*) m_pBits; + int rowbytesize = rows/8; + int rowregsize = rows/(sizeof(REGISTER_SIZE) * 8); + for(int i = 0; i +#include +#include + +#define DEFAULT_BITSIZE 128 + +static const uint8_t REVERSE_NIBBLE_ORDER[16] = + {0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF}; + +static const uint8_t REVERSE_BYTE_ORDER[256] = + {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, \ + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, \ + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, \ + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, \ + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, \ + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, \ + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, \ + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, \ + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, \ + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, \ + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, \ + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, \ + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, \ + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, \ + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, \ + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF + }; + +static const uint8_t RESET_BIT_POSITIONS[9] = + {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; + +static const uint8_t RESET_BIT_POSITIONS_INV[9] = + {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF}; + +static const uint8_t GET_BIT_POSITIONS[9] = + {0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00}; + +static const uint8_t GET_BIT_POSITIONS_INV[9] = + {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00}; + +static const int INT_MASK[8] = + {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01}; + +static const int FIRST_MASK_SHIFT[8] = + {0xFF00, 0x7F80, 0x3FC0, 0x1FE0, 0x0FF0, 0x07F8, 0x03FC, 0x01FE}; + +static const uint8_t MASK_BIT[8] = + {0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1}; + +static const uint8_t BIT[8] = + {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; + +static const uint8_t CMASK_BIT[8] = + {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe}; + +static const uint8_t C_BIT[8] = + {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}; + +static const uint8_t MASK_SET_BIT[2][8] = + {{0,0,0,0,0,0,0,0},{0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1}}; + +static const uint8_t MASK_SET_BIT_C[2][8] = + {{0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1},{0,0,0,0,0,0,0,0}}; + +static const uint8_t SET_BIT_C[2][8] = + {{0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80},{0,0,0,0,0,0,0,0}}; + +const uint8_t SELECT_BIT_POSITIONS[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; + + +#ifdef MACHINE_SIZE_32 +static const REGISTER_SIZE TRANSPOSITION_MASKS[6] = + {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF}; +static const REGISTER_SIZE TRANSPOSITION_MASKS_INV[6] = + {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000}; +#else + #ifdef MACHINE_SIZE_64 +static const REGISTER_SIZE TRANSPOSITION_MASKS[6] = + {0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F, 0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF, 0x00000000FFFFFFFF}; +static const REGISTER_SIZE TRANSPOSITION_MASKS_INV[6] = + {0xAAAAAAAAAAAAAAAA, 0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0, 0xFF00FF00FF00FF00, 0xFFFF0000FFFF0000, 0xFFFFFFFF00000000}; + #else + #endif +#endif + +static const size_t SHIFTVAL = 3;//sizeof(REGSIZE); + +class CBitVector +{ +public: + CBitVector(){ Init(); } + CBitVector(int bits){ Init(); Create(bits);} + CBitVector(int bits, crypto* crypt){ Init(); CreateRand(bits, crypt);} + + void Init() {m_pBits = NULL; m_nByteSize = 0; m_cCrypto = NULL;} + + //~CBitVector(){ if(m_pBits) free(m_pBits); } + void delCBitVector(){ if(m_nByteSize > 0) free(m_pBits); m_nByteSize = 0; m_pBits = NULL; } + + /* Use this function to initialize the AES round key which can then be used to generate further random bits */ + void InitRand(crypto* crypt) { m_cCrypto = crypt; } + + /* Fill the bitvector with random values and pre-initialize the key to the seed-key*/ + void FillRand(int bits, crypto* crypt); + + /* Fill random values using the pre-defined AES key */ + void FillRand(int bits); + + /** + * Create Operations + */ + + //Create in bits and bytes + void Create(int bits); + void CreateBytes(int bytes) { Create(bytes<<3); } + void CreateZeros(int bits) { Create(bits); memset(m_pBits, 0, m_nByteSize); } + //Create and fill with random values + void CreateRand(int bits, crypto* crypt); + //Create an abstract array of values + void Create(int numelements, int elementlength); + void Create(int numelements, int elementlength, crypto* crypt); + //Create an abstract two-dimensional array of values + void Create(int numelementsDimA, int numelementsDimB, int elementlength); + void Create(int numelementsDimA, int numelementsDimB, int elementlength, crypto* crypt); + + + /* + * Management operations + */ + void ResizeinBytes(int newSizeBytes); + void Reset() { memset(m_pBits, 0, m_nByteSize); } + void ResetFromTo(int frombyte, int tobyte) { memset(m_pBits+frombyte, 0, tobyte-frombyte); } + void SetToOne() { memset(m_pBits, 0xFF, m_nByteSize); } + int GetSize(){ return m_nByteSize; } + BOOL IsEqual(CBitVector& vec); + BOOL IsEqual(CBitVector& vec, int from, int to); + + void SetElementLength(int elelen) { m_nElementLength = elelen; } + + + /* + * Copy operations + */ + + void Copy(CBitVector& vec) { Copy(vec.GetArr(), 0, vec.GetSize()); } + void Copy(CBitVector& vec, int pos, int len) { Copy(vec.GetArr(), pos, len); } + void Copy(uint8_t* p, int pos, int len); + + + + void XOR_no_mask(int p, int bitPos, int bitLen); + unsigned int GetInt(int bitPos, int bitLen); + #define GetIntBitsFromLen(x, from, len) ( ( (x & ( ( (2<<(len))-1) << from )) >> from) & 0xFF) + #define GetMask(len) (( (1<<(len))-1)) + + void ORByte(int pos, uint8_t p); + + + /* + * Bitwise operations + */ + uint8_t GetBit(int idx) { return !!(m_pBits[idx>>3] & MASK_BIT[idx & 0x7]); } + void SetBit(int idx, uint8_t b) { m_pBits[idx>>3] = (m_pBits[idx>>3] & CMASK_BIT[idx & 0x7]) | MASK_SET_BIT_C[!(b&0x01)][idx & 0x7]; } + void XORBit(int idx, uint8_t b) { m_pBits[idx>>3] ^= MASK_SET_BIT_C[!(b&0x01)][idx & 0x7]; } + void ANDBit(int idx, uint8_t b) { if(!b) m_pBits[idx>>3] &= CMASK_BIT[idx & 0x7]; } + + //used to access bits in the regular order + uint8_t GetBitNoMask(uint64_t idx) { return !!(m_pBits[idx>>3] & BIT[idx & 0x7]); } + //uint8_t GetBitNoMask(int idx) { return GetBitNoMask((uint64_t) idx);}; + void SetBitNoMask(int idx, uint8_t b) { m_pBits[idx>>3] = (m_pBits[idx>>3] & C_BIT[idx & 0x7]) | SET_BIT_C[!(b&0x01)][idx & 0x7]; } + void XORBitNoMask(int idx, uint8_t b) { m_pBits[idx>>3] ^= SET_BIT_C[!(b&0x01)][idx & 0x7]; } + void ANDBitNoMask(int idx, uint8_t b) { if(!b) m_pBits[idx>>3] &= C_BIT[idx & 0x7]; } + + + /* + * Single byte operations + */ + void SetByte(int idx, uint8_t p) { m_pBits[idx] = p;} + uint8_t GetByte(int idx) { return m_pBits[idx]; } + void XORByte(int idx, uint8_t b) { m_pBits[idx] ^= b; } + void ANDByte(int idx, uint8_t b) { m_pBits[idx] &= b; } + + /* + * Get Operations + */ + void GetBits(uint8_t* p, uint64_t pos, uint64_t len); + //void GetBits(uint8_t* p, int pos, int len) {GetBits(p, (uint64_t) pos, (uint64_t) len);}; + //void GetBytes(uint8_t* p, int pos, int len) {GetBytes(p, (uint64_t) pos, (uint64_t) len); }; + void GetBytes(uint8_t* p, uint64_t pos, uint64_t len); + template void GetBytes(T* dst, T* src, T* lim); + //template T Get(int pos, int len); + template T Get(uint64_t pos, uint64_t len) + { + T val = 0; + GetBits((uint8_t*) &val, pos, len); + return val; + } + + /* + * Set Operations + */ + void SetBits(uint8_t* p, int pos, int len); + void SetBytes(uint8_t* p, int pos, int len); + template void SetBytes(T* dst, T* src, T* lim); + template void Set(T val, int pos, int len) { SetBits((uint8_t*) &val, pos, len); } + void SetBitsToZero(int bitpos, int bitlen); + + + /* + * XOR Operations + */ + void XORBytes(uint8_t* p, int pos, int len) {XORBytes(p, (uint64_t) pos, (uint64_t) len);}; + void XORBytes(uint8_t* p, uint32_t pos, uint32_t len) {XORBytes(p, (uint64_t) pos, (uint64_t) len);}; + void XORBytes(uint8_t* p, int len) { XORBytes(p, 0, len); } + void XORBytes(uint8_t* p, uint64_t pos, uint64_t len); + void XORVector(CBitVector &vec, int pos, int len) { XORBytes(vec.GetArr(), pos, len); } + template void XOR(T val, int pos, int len) { XORBits((uint8_t*) &val, pos, len); } + void XORBits(uint8_t* p, int pos, int len); + void XORBits(uint8_t* p, uint64_t pos, uint64_t len); + + void XORBitsPosOffset(uint8_t* p, int ppos, int pos, int len); + template void XORBytes(T* dst, T* src, T* lim); + void XORRepeat(uint8_t* p, int pos, int len, int num); + void XORBytesReverse(uint8_t* p, int pos, int len); + + + + /* + * AND Operations + */ + void ANDBytes(uint8_t* p, int pos, int len); + template void ANDBytes(T* dst, T* src, T* lim); + + + /* + * Set operations + */ + void SetXOR(uint8_t* p, uint8_t* q, int pos, int len); + void SetAND(uint8_t* p, uint8_t* q, int pos, int len); + + /* + * Buffer access operations + */ + uint8_t* GetArr(){ return m_pBits;} + void AttachBuf(uint8_t* p, int size=-1){ m_pBits = p; m_nByteSize = size;} + void DetachBuf(){ m_pBits = NULL; m_nByteSize = 0;} + + + /* + * Print Operations + */ + void Print(int fromBit, int toBit); + void PrintHex(); + void PrintHex(int fromByte, int toByte); + void PrintBinary() { Print(0, m_nByteSize<<3); } + void PrintContent(); + void PrintBinaryMasked(int from, int to); + + + /* + * If the cbitvector is abstracted to an array of elements with m_nElementLength bits size, these methods can be used for easier access + */ + template T Get(int i){ return Get(i*m_nElementLength, m_nElementLength);} + template void Set(T val, int i){ Set(val, i*m_nElementLength, m_nElementLength);} + /* + * The same as the above methods only for two-dimensional access + */ + template T Get2D(int i, int j){ return Get((i * m_nNumElementsDimB + j) * m_nElementLength, m_nElementLength);} + template void Set2D(T val, int i, int j){ Set(val, (i * m_nNumElementsDimB + j) * m_nElementLength, m_nElementLength);} + //useful when accessing elements using an index + + + //View the cbitvector as a rows x columns matrix and transpose + void EklundhBitTranspose(int rows, int columns); + void SimpleTranspose(int rows, int columns); + + + +private: + uint8_t* m_pBits; + int m_nByteSize; + crypto* m_cCrypto; + int m_nBits; //The exact number of bits + int m_nElementLength; + int m_nNumElements; + int m_nNumElementsDimB; +}; + + + + +#endif /* BITVECTOR_H_ */ diff --git a/src/util/codewords.cpp b/src/util/codewords.cpp new file mode 100644 index 0000000..842ee71 --- /dev/null +++ b/src/util/codewords.cpp @@ -0,0 +1,25 @@ +/* + * codewords.cpp + * + * Created on: Oct 10, 2014 + * Author: mzohner + */ + + +#include "codewords.h" + +/*void readCodeWords(uint64_t** codewords) { + uint32_t i, j, k; + for(i = 0; i < m_nCodewords; i++) { + for(j = 0; j < (m_nCWIntlen * sizeof(uint32_t)) / sizeof(uint64_t); j++) { + codewords[i][j] = 0; + for(k = 0; k < sizeof(uint64_t) / sizeof(uint32_t); k++) { + codewords[i][j] |= (((REGISTER_SIZE) CODE_MATRIX[i][j*sizeof(REGISTER_SIZE) / sizeof(uint32_t)+k]) << (k * 8 * sizeof(uint32_t))); + //cout << (hex) << CODE_MATRIX[i][j*2+k]; + } + // cout << (hex) << codewords[i][j] << ", "; + } + //cout << endl; + } +} +*/ diff --git a/src/util/codewords.h b/src/util/codewords.h new file mode 100644 index 0000000..1858fa7 --- /dev/null +++ b/src/util/codewords.h @@ -0,0 +1,283 @@ +#ifndef __CODEWORDS_H_ +#define __CODEWORDS_H_ + +#include "typedefs.h" + +static const uint32_t m_nCodewords = 256; +static const uint32_t m_nCWIntlen = 8; + +static const uint32_t CODE_MATRIX[m_nCodewords][m_nCWIntlen] = { \ + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, \ + {0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, \ + {0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc}, \ + {0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666}, \ + {0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0}, \ + {0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a}, \ + {0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c}, \ + {0x96969696, 0x96969696, 0x96969696, 0x96969696, 0x96969696, 0x96969696, 0x96969696, 0x96969696}, \ + {0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00}, \ + {0x55aa55aa, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa}, \ + {0x33cc33cc, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc}, \ + {0x99669966, 0x99669966, 0x99669966, 0x99669966, 0x99669966, 0x99669966, 0x99669966, 0x99669966}, \ + {0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0}, \ + {0xa55aa55a, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a}, \ + {0xc33cc33c, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c}, \ + {0x69966996, 0x69966996, 0x69966996, 0x69966996, 0x69966996, 0x69966996, 0x69966996, 0x69966996}, \ + {0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000}, \ + {0x5555aaaa, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa}, \ + {0x3333cccc, 0x3333cccc, 0x3333cccc, 0x3333cccc, 0x3333cccc, 0x3333cccc, 0x3333cccc, 0x3333cccc}, \ + {0x99996666, 0x99996666, 0x99996666, 0x99996666, 0x99996666, 0x99996666, 0x99996666, 0x99996666}, \ + {0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0}, \ + {0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a}, \ + {0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c}, \ + {0x69699696, 0x69699696, 0x69699696, 0x69699696, 0x69699696, 0x69699696, 0x69699696, 0x69699696}, \ + {0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00}, \ + {0xaa5555aa, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa}, \ + {0xcc3333cc, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc}, \ + {0x66999966, 0x66999966, 0x66999966, 0x66999966, 0x66999966, 0x66999966, 0x66999966, 0x66999966}, \ + {0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0}, \ + {0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a}, \ + {0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c}, \ + {0x96696996, 0x96696996, 0x96696996, 0x96696996, 0x96696996, 0x96696996, 0x96696996, 0x96696996}, \ + {0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, \ + {0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa}, \ + {0x33333333, 0xcccccccc, 0x33333333, 0xcccccccc, 0x33333333, 0xcccccccc, 0x33333333, 0xcccccccc}, \ + {0x99999999, 0x66666666, 0x99999999, 0x66666666, 0x99999999, 0x66666666, 0x99999999, 0x66666666}, \ + {0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0}, \ + {0xa5a5a5a5, 0x5a5a5a5a, 0xa5a5a5a5, 0x5a5a5a5a, 0xa5a5a5a5, 0x5a5a5a5a, 0xa5a5a5a5, 0x5a5a5a5a}, \ + {0xc3c3c3c3, 0x3c3c3c3c, 0xc3c3c3c3, 0x3c3c3c3c, 0xc3c3c3c3, 0x3c3c3c3c, 0xc3c3c3c3, 0x3c3c3c3c}, \ + {0x69696969, 0x96969696, 0x69696969, 0x96969696, 0x69696969, 0x96969696, 0x69696969, 0x96969696}, \ + {0x00ff00ff, 0xff00ff00, 0x00ff00ff, 0xff00ff00, 0x00ff00ff, 0xff00ff00, 0x00ff00ff, 0xff00ff00}, \ + {0xaa55aa55, 0x55aa55aa, 0xaa55aa55, 0x55aa55aa, 0xaa55aa55, 0x55aa55aa, 0xaa55aa55, 0x55aa55aa}, \ + {0xcc33cc33, 0x33cc33cc, 0xcc33cc33, 0x33cc33cc, 0xcc33cc33, 0x33cc33cc, 0xcc33cc33, 0x33cc33cc}, \ + {0x66996699, 0x99669966, 0x66996699, 0x99669966, 0x66996699, 0x99669966, 0x66996699, 0x99669966}, \ + {0xf00ff00f, 0x0ff00ff0, 0xf00ff00f, 0x0ff00ff0, 0xf00ff00f, 0x0ff00ff0, 0xf00ff00f, 0x0ff00ff0}, \ + {0x5aa55aa5, 0xa55aa55a, 0x5aa55aa5, 0xa55aa55a, 0x5aa55aa5, 0xa55aa55a, 0x5aa55aa5, 0xa55aa55a}, \ + {0x3cc33cc3, 0xc33cc33c, 0x3cc33cc3, 0xc33cc33c, 0x3cc33cc3, 0xc33cc33c, 0x3cc33cc3, 0xc33cc33c}, \ + {0x96699669, 0x69966996, 0x96699669, 0x69966996, 0x96699669, 0x69966996, 0x96699669, 0x69966996}, \ + {0x0000ffff, 0xffff0000, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xffff0000}, \ + {0xaaaa5555, 0x5555aaaa, 0xaaaa5555, 0x5555aaaa, 0xaaaa5555, 0x5555aaaa, 0xaaaa5555, 0x5555aaaa}, \ + {0xcccc3333, 0x3333cccc, 0xcccc3333, 0x3333cccc, 0xcccc3333, 0x3333cccc, 0xcccc3333, 0x3333cccc}, \ + {0x66669999, 0x99996666, 0x66669999, 0x99996666, 0x66669999, 0x99996666, 0x66669999, 0x99996666}, \ + {0xf0f00f0f, 0x0f0ff0f0, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f00f0f, 0x0f0ff0f0}, \ + {0x5a5aa5a5, 0xa5a55a5a, 0x5a5aa5a5, 0xa5a55a5a, 0x5a5aa5a5, 0xa5a55a5a, 0x5a5aa5a5, 0xa5a55a5a}, \ + {0x3c3cc3c3, 0xc3c33c3c, 0x3c3cc3c3, 0xc3c33c3c, 0x3c3cc3c3, 0xc3c33c3c, 0x3c3cc3c3, 0xc3c33c3c}, \ + {0x96966969, 0x69699696, 0x96966969, 0x69699696, 0x96966969, 0x69699696, 0x96966969, 0x69699696}, \ + {0xff0000ff, 0x00ffff00, 0xff0000ff, 0x00ffff00, 0xff0000ff, 0x00ffff00, 0xff0000ff, 0x00ffff00}, \ + {0x55aaaa55, 0xaa5555aa, 0x55aaaa55, 0xaa5555aa, 0x55aaaa55, 0xaa5555aa, 0x55aaaa55, 0xaa5555aa}, \ + {0x33cccc33, 0xcc3333cc, 0x33cccc33, 0xcc3333cc, 0x33cccc33, 0xcc3333cc, 0x33cccc33, 0xcc3333cc}, \ + {0x99666699, 0x66999966, 0x99666699, 0x66999966, 0x99666699, 0x66999966, 0x99666699, 0x66999966}, \ + {0x0ff0f00f, 0xf00f0ff0, 0x0ff0f00f, 0xf00f0ff0, 0x0ff0f00f, 0xf00f0ff0, 0x0ff0f00f, 0xf00f0ff0}, \ + {0xa55a5aa5, 0x5aa5a55a, 0xa55a5aa5, 0x5aa5a55a, 0xa55a5aa5, 0x5aa5a55a, 0xa55a5aa5, 0x5aa5a55a}, \ + {0xc33c3cc3, 0x3cc3c33c, 0xc33c3cc3, 0x3cc3c33c, 0xc33c3cc3, 0x3cc3c33c, 0xc33c3cc3, 0x3cc3c33c}, \ + {0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x69969669, 0x96696996}, \ + {0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000}, \ + {0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa}, \ + {0x33333333, 0x33333333, 0xcccccccc, 0xcccccccc, 0x33333333, 0x33333333, 0xcccccccc, 0xcccccccc}, \ + {0x99999999, 0x99999999, 0x66666666, 0x66666666, 0x99999999, 0x99999999, 0x66666666, 0x66666666}, \ + {0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0}, \ + {0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a}, \ + {0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c, 0x3c3c3c3c}, \ + {0x69696969, 0x69696969, 0x96969696, 0x96969696, 0x69696969, 0x69696969, 0x96969696, 0x96969696}, \ + {0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00, 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00}, \ + {0xaa55aa55, 0xaa55aa55, 0x55aa55aa, 0x55aa55aa, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa, 0x55aa55aa}, \ + {0xcc33cc33, 0xcc33cc33, 0x33cc33cc, 0x33cc33cc, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc, 0x33cc33cc}, \ + {0x66996699, 0x66996699, 0x99669966, 0x99669966, 0x66996699, 0x66996699, 0x99669966, 0x99669966}, \ + {0xf00ff00f, 0xf00ff00f, 0x0ff00ff0, 0x0ff00ff0, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0, 0x0ff00ff0}, \ + {0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a, 0xa55aa55a}, \ + {0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c, 0xc33cc33c, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c, 0xc33cc33c}, \ + {0x96699669, 0x96699669, 0x69966996, 0x69966996, 0x96699669, 0x96699669, 0x69966996, 0x69966996}, \ + {0x0000ffff, 0x0000ffff, 0xffff0000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0xffff0000, 0xffff0000}, \ + {0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa}, \ + {0xcccc3333, 0xcccc3333, 0x3333cccc, 0x3333cccc, 0xcccc3333, 0xcccc3333, 0x3333cccc, 0x3333cccc}, \ + {0x66669999, 0x66669999, 0x99996666, 0x99996666, 0x66669999, 0x66669999, 0x99996666, 0x99996666}, \ + {0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0}, \ + {0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a, 0xa5a55a5a, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a, 0xa5a55a5a}, \ + {0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c, 0xc3c33c3c, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c, 0xc3c33c3c}, \ + {0x96966969, 0x96966969, 0x69699696, 0x69699696, 0x96966969, 0x96966969, 0x69699696, 0x69699696}, \ + {0xff0000ff, 0xff0000ff, 0x00ffff00, 0x00ffff00, 0xff0000ff, 0xff0000ff, 0x00ffff00, 0x00ffff00}, \ + {0x55aaaa55, 0x55aaaa55, 0xaa5555aa, 0xaa5555aa, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa, 0xaa5555aa}, \ + {0x33cccc33, 0x33cccc33, 0xcc3333cc, 0xcc3333cc, 0x33cccc33, 0x33cccc33, 0xcc3333cc, 0xcc3333cc}, \ + {0x99666699, 0x99666699, 0x66999966, 0x66999966, 0x99666699, 0x99666699, 0x66999966, 0x66999966}, \ + {0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0, 0xf00f0ff0, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0, 0xf00f0ff0}, \ + {0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a, 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a, 0x5aa5a55a}, \ + {0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c, 0x3cc3c33c, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c, 0x3cc3c33c}, \ + {0x69969669, 0x69969669, 0x96696996, 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x96696996}, \ + {0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, \ + {0xaaaaaaaa, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0xaaaaaaaa}, \ + {0xcccccccc, 0x33333333, 0x33333333, 0xcccccccc, 0xcccccccc, 0x33333333, 0x33333333, 0xcccccccc}, \ + {0x66666666, 0x99999999, 0x99999999, 0x66666666, 0x66666666, 0x99999999, 0x99999999, 0x66666666}, \ + {0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0}, \ + {0x5a5a5a5a, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a}, \ + {0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c}, \ + {0x96969696, 0x69696969, 0x69696969, 0x96969696, 0x96969696, 0x69696969, 0x69696969, 0x96969696}, \ + {0xff00ff00, 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00, 0x00ff00ff, 0x00ff00ff, 0xff00ff00}, \ + {0x55aa55aa, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa, 0x55aa55aa, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa}, \ + {0x33cc33cc, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc, 0x33cc33cc, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc}, \ + {0x99669966, 0x66996699, 0x66996699, 0x99669966, 0x99669966, 0x66996699, 0x66996699, 0x99669966}, \ + {0x0ff00ff0, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0, 0x0ff00ff0, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0}, \ + {0xa55aa55a, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a}, \ + {0xc33cc33c, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c, 0xc33cc33c, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c}, \ + {0x69966996, 0x96699669, 0x96699669, 0x69966996, 0x69966996, 0x96699669, 0x96699669, 0x69966996}, \ + {0xffff0000, 0x0000ffff, 0x0000ffff, 0xffff0000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0xffff0000}, \ + {0x5555aaaa, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa}, \ + {0x3333cccc, 0xcccc3333, 0xcccc3333, 0x3333cccc, 0x3333cccc, 0xcccc3333, 0xcccc3333, 0x3333cccc}, \ + {0x99996666, 0x66669999, 0x66669999, 0x99996666, 0x99996666, 0x66669999, 0x66669999, 0x99996666}, \ + {0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0}, \ + {0xa5a55a5a, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a, 0xa5a55a5a, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a}, \ + {0xc3c33c3c, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c, 0xc3c33c3c, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c}, \ + {0x69699696, 0x96966969, 0x96966969, 0x69699696, 0x69699696, 0x96966969, 0x96966969, 0x69699696}, \ + {0x00ffff00, 0xff0000ff, 0xff0000ff, 0x00ffff00, 0x00ffff00, 0xff0000ff, 0xff0000ff, 0x00ffff00}, \ + {0xaa5555aa, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa, 0xaa5555aa, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa}, \ + {0xcc3333cc, 0x33cccc33, 0x33cccc33, 0xcc3333cc, 0xcc3333cc, 0x33cccc33, 0x33cccc33, 0xcc3333cc}, \ + {0x66999966, 0x99666699, 0x99666699, 0x66999966, 0x66999966, 0x99666699, 0x99666699, 0x66999966}, \ + {0xf00f0ff0, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0, 0xf00f0ff0, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0}, \ + {0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a, 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a}, \ + {0x3cc3c33c, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c, 0x3cc3c33c, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c}, \ + {0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x96696996, 0x69969669, 0x69969669, 0x96696996}, \ + {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, \ + {0x55555555, 0x55555555, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, \ + {0x33333333, 0x33333333, 0x33333333, 0x33333333, 0xcccccccc, 0xcccccccc, 0xcccccccc, 0xcccccccc}, \ + {0x99999999, 0x99999999, 0x99999999, 0x99999999, 0x66666666, 0x66666666, 0x66666666, 0x66666666}, \ + {0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0}, \ + {0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a}, \ + {0xc3c3c3c3, 0xc3c3c3c3, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c}, \ + {0x69696969, 0x69696969, 0x69696969, 0x69696969, 0x96969696, 0x96969696, 0x96969696, 0x96969696}, \ + {0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00}, \ + {0xaa55aa55, 0xaa55aa55, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa, 0x55aa55aa}, \ + {0xcc33cc33, 0xcc33cc33, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc, 0x33cc33cc}, \ + {0x66996699, 0x66996699, 0x66996699, 0x66996699, 0x99669966, 0x99669966, 0x99669966, 0x99669966}, \ + {0xf00ff00f, 0xf00ff00f, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0, 0x0ff00ff0}, \ + {0x5aa55aa5, 0x5aa55aa5, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a, 0xa55aa55a}, \ + {0x3cc33cc3, 0x3cc33cc3, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c, 0xc33cc33c}, \ + {0x96699669, 0x96699669, 0x96699669, 0x96699669, 0x69966996, 0x69966996, 0x69966996, 0x69966996}, \ + {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000}, \ + {0xaaaa5555, 0xaaaa5555, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa, 0x5555aaaa}, \ + {0xcccc3333, 0xcccc3333, 0xcccc3333, 0xcccc3333, 0x3333cccc, 0x3333cccc, 0x3333cccc, 0x3333cccc}, \ + {0x66669999, 0x66669999, 0x66669999, 0x66669999, 0x99996666, 0x99996666, 0x99996666, 0x99996666}, \ + {0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0, 0x0f0ff0f0}, \ + {0x5a5aa5a5, 0x5a5aa5a5, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a, 0xa5a55a5a}, \ + {0x3c3cc3c3, 0x3c3cc3c3, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c, 0xc3c33c3c}, \ + {0x96966969, 0x96966969, 0x96966969, 0x96966969, 0x69699696, 0x69699696, 0x69699696, 0x69699696}, \ + {0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x00ffff00, 0x00ffff00, 0x00ffff00, 0x00ffff00}, \ + {0x55aaaa55, 0x55aaaa55, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa, 0xaa5555aa}, \ + {0x33cccc33, 0x33cccc33, 0x33cccc33, 0x33cccc33, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc, 0xcc3333cc}, \ + {0x99666699, 0x99666699, 0x99666699, 0x99666699, 0x66999966, 0x66999966, 0x66999966, 0x66999966}, \ + {0x0ff0f00f, 0x0ff0f00f, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0, 0xf00f0ff0}, \ + {0xa55a5aa5, 0xa55a5aa5, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a, 0x5aa5a55a}, \ + {0xc33c3cc3, 0xc33c3cc3, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c, 0x3cc3c33c}, \ + {0x69969669, 0x69969669, 0x69969669, 0x69969669, 0x96696996, 0x96696996, 0x96696996, 0x96696996}, \ + {0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000}, \ + {0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555, 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa}, \ + {0xcccccccc, 0x33333333, 0xcccccccc, 0x33333333, 0x33333333, 0xcccccccc, 0x33333333, 0xcccccccc}, \ + {0x66666666, 0x99999999, 0x66666666, 0x99999999, 0x99999999, 0x66666666, 0x99999999, 0x66666666}, \ + {0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0}, \ + {0x5a5a5a5a, 0xa5a5a5a5, 0x5a5a5a5a, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0xa5a5a5a5, 0x5a5a5a5a}, \ + {0x3c3c3c3c, 0xc3c3c3c3, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c, 0xc3c3c3c3, 0x3c3c3c3c}, \ + {0x96969696, 0x69696969, 0x96969696, 0x69696969, 0x69696969, 0x96969696, 0x69696969, 0x96969696}, \ + {0xff00ff00, 0x00ff00ff, 0xff00ff00, 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0x00ff00ff, 0xff00ff00}, \ + {0x55aa55aa, 0xaa55aa55, 0x55aa55aa, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa, 0xaa55aa55, 0x55aa55aa}, \ + {0x33cc33cc, 0xcc33cc33, 0x33cc33cc, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc, 0xcc33cc33, 0x33cc33cc}, \ + {0x99669966, 0x66996699, 0x99669966, 0x66996699, 0x66996699, 0x99669966, 0x66996699, 0x99669966}, \ + {0x0ff00ff0, 0xf00ff00f, 0x0ff00ff0, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0, 0xf00ff00f, 0x0ff00ff0}, \ + {0xa55aa55a, 0x5aa55aa5, 0xa55aa55a, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a, 0x5aa55aa5, 0xa55aa55a}, \ + {0xc33cc33c, 0x3cc33cc3, 0xc33cc33c, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c, 0x3cc33cc3, 0xc33cc33c}, \ + {0x69966996, 0x96699669, 0x69966996, 0x96699669, 0x96699669, 0x69966996, 0x96699669, 0x69966996}, \ + {0xffff0000, 0x0000ffff, 0xffff0000, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xffff0000}, \ + {0x5555aaaa, 0xaaaa5555, 0x5555aaaa, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0xaaaa5555, 0x5555aaaa}, \ + {0x3333cccc, 0xcccc3333, 0x3333cccc, 0xcccc3333, 0xcccc3333, 0x3333cccc, 0xcccc3333, 0x3333cccc}, \ + {0x99996666, 0x66669999, 0x99996666, 0x66669999, 0x66669999, 0x99996666, 0x66669999, 0x99996666}, \ + {0x0f0ff0f0, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f00f0f, 0x0f0ff0f0}, \ + {0xa5a55a5a, 0x5a5aa5a5, 0xa5a55a5a, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a, 0x5a5aa5a5, 0xa5a55a5a}, \ + {0xc3c33c3c, 0x3c3cc3c3, 0xc3c33c3c, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c, 0x3c3cc3c3, 0xc3c33c3c}, \ + {0x69699696, 0x96966969, 0x69699696, 0x96966969, 0x96966969, 0x69699696, 0x96966969, 0x69699696}, \ + {0x00ffff00, 0xff0000ff, 0x00ffff00, 0xff0000ff, 0xff0000ff, 0x00ffff00, 0xff0000ff, 0x00ffff00}, \ + {0xaa5555aa, 0x55aaaa55, 0xaa5555aa, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa, 0x55aaaa55, 0xaa5555aa}, \ + {0xcc3333cc, 0x33cccc33, 0xcc3333cc, 0x33cccc33, 0x33cccc33, 0xcc3333cc, 0x33cccc33, 0xcc3333cc}, \ + {0x66999966, 0x99666699, 0x66999966, 0x99666699, 0x99666699, 0x66999966, 0x99666699, 0x66999966}, \ + {0xf00f0ff0, 0x0ff0f00f, 0xf00f0ff0, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0, 0x0ff0f00f, 0xf00f0ff0}, \ + {0x5aa5a55a, 0xa55a5aa5, 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a, 0xa55a5aa5, 0x5aa5a55a}, \ + {0x3cc3c33c, 0xc33c3cc3, 0x3cc3c33c, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c, 0xc33c3cc3, 0x3cc3c33c}, \ + {0x96696996, 0x69969669, 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996}, \ + {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000}, \ + {0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa}, \ + {0xcccccccc, 0xcccccccc, 0x33333333, 0x33333333, 0x33333333, 0x33333333, 0xcccccccc, 0xcccccccc}, \ + {0x66666666, 0x66666666, 0x99999999, 0x99999999, 0x99999999, 0x99999999, 0x66666666, 0x66666666}, \ + {0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0}, \ + {0x5a5a5a5a, 0x5a5a5a5a, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a}, \ + {0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c, 0x3c3c3c3c}, \ + {0x96969696, 0x96969696, 0x69696969, 0x69696969, 0x69696969, 0x69696969, 0x96969696, 0x96969696}, \ + {0xff00ff00, 0xff00ff00, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0xff00ff00, 0xff00ff00}, \ + {0x55aa55aa, 0x55aa55aa, 0xaa55aa55, 0xaa55aa55, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa, 0x55aa55aa}, \ + {0x33cc33cc, 0x33cc33cc, 0xcc33cc33, 0xcc33cc33, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc, 0x33cc33cc}, \ + {0x99669966, 0x99669966, 0x66996699, 0x66996699, 0x66996699, 0x66996699, 0x99669966, 0x99669966}, \ + {0x0ff00ff0, 0x0ff00ff0, 0xf00ff00f, 0xf00ff00f, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0, 0x0ff00ff0}, \ + {0xa55aa55a, 0xa55aa55a, 0x5aa55aa5, 0x5aa55aa5, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a, 0xa55aa55a}, \ + {0xc33cc33c, 0xc33cc33c, 0x3cc33cc3, 0x3cc33cc3, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c, 0xc33cc33c}, \ + {0x69966996, 0x69966996, 0x96699669, 0x96699669, 0x96699669, 0x96699669, 0x69966996, 0x69966996}, \ + {0xffff0000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0xffff0000}, \ + {0x5555aaaa, 0x5555aaaa, 0xaaaa5555, 0xaaaa5555, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa, 0x5555aaaa}, \ + {0x3333cccc, 0x3333cccc, 0xcccc3333, 0xcccc3333, 0xcccc3333, 0xcccc3333, 0x3333cccc, 0x3333cccc}, \ + {0x99996666, 0x99996666, 0x66669999, 0x66669999, 0x66669999, 0x66669999, 0x99996666, 0x99996666}, \ + {0x0f0ff0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0}, \ + {0xa5a55a5a, 0xa5a55a5a, 0x5a5aa5a5, 0x5a5aa5a5, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a, 0xa5a55a5a}, \ + {0xc3c33c3c, 0xc3c33c3c, 0x3c3cc3c3, 0x3c3cc3c3, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c, 0xc3c33c3c}, \ + {0x69699696, 0x69699696, 0x96966969, 0x96966969, 0x96966969, 0x96966969, 0x69699696, 0x69699696}, \ + {0x00ffff00, 0x00ffff00, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x00ffff00, 0x00ffff00}, \ + {0xaa5555aa, 0xaa5555aa, 0x55aaaa55, 0x55aaaa55, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa, 0xaa5555aa}, \ + {0xcc3333cc, 0xcc3333cc, 0x33cccc33, 0x33cccc33, 0x33cccc33, 0x33cccc33, 0xcc3333cc, 0xcc3333cc}, \ + {0x66999966, 0x66999966, 0x99666699, 0x99666699, 0x99666699, 0x99666699, 0x66999966, 0x66999966}, \ + {0xf00f0ff0, 0xf00f0ff0, 0x0ff0f00f, 0x0ff0f00f, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0, 0xf00f0ff0}, \ + {0x5aa5a55a, 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a, 0x5aa5a55a}, \ + {0x3cc3c33c, 0x3cc3c33c, 0xc33c3cc3, 0xc33c3cc3, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c, 0x3cc3c33c}, \ + {0x96696996, 0x96696996, 0x69969669, 0x69969669, 0x69969669, 0x69969669, 0x96696996, 0x96696996}, \ + {0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, \ + {0x55555555, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555, 0x55555555, 0xaaaaaaaa}, \ + {0x33333333, 0xcccccccc, 0xcccccccc, 0x33333333, 0xcccccccc, 0x33333333, 0x33333333, 0xcccccccc}, \ + {0x99999999, 0x66666666, 0x66666666, 0x99999999, 0x66666666, 0x99999999, 0x99999999, 0x66666666}, \ + {0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0}, \ + {0xa5a5a5a5, 0x5a5a5a5a, 0x5a5a5a5a, 0xa5a5a5a5, 0x5a5a5a5a, 0xa5a5a5a5, 0xa5a5a5a5, 0x5a5a5a5a}, \ + {0xc3c3c3c3, 0x3c3c3c3c, 0x3c3c3c3c, 0xc3c3c3c3, 0x3c3c3c3c, 0xc3c3c3c3, 0xc3c3c3c3, 0x3c3c3c3c}, \ + {0x69696969, 0x96969696, 0x96969696, 0x69696969, 0x96969696, 0x69696969, 0x69696969, 0x96969696}, \ + {0x00ff00ff, 0xff00ff00, 0xff00ff00, 0x00ff00ff, 0xff00ff00, 0x00ff00ff, 0x00ff00ff, 0xff00ff00}, \ + {0xaa55aa55, 0x55aa55aa, 0x55aa55aa, 0xaa55aa55, 0x55aa55aa, 0xaa55aa55, 0xaa55aa55, 0x55aa55aa}, \ + {0xcc33cc33, 0x33cc33cc, 0x33cc33cc, 0xcc33cc33, 0x33cc33cc, 0xcc33cc33, 0xcc33cc33, 0x33cc33cc}, \ + {0x66996699, 0x99669966, 0x99669966, 0x66996699, 0x99669966, 0x66996699, 0x66996699, 0x99669966}, \ + {0xf00ff00f, 0x0ff00ff0, 0x0ff00ff0, 0xf00ff00f, 0x0ff00ff0, 0xf00ff00f, 0xf00ff00f, 0x0ff00ff0}, \ + {0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0x5aa55aa5, 0xa55aa55a, 0x5aa55aa5, 0x5aa55aa5, 0xa55aa55a}, \ + {0x3cc33cc3, 0xc33cc33c, 0xc33cc33c, 0x3cc33cc3, 0xc33cc33c, 0x3cc33cc3, 0x3cc33cc3, 0xc33cc33c}, \ + {0x96699669, 0x69966996, 0x69966996, 0x96699669, 0x69966996, 0x96699669, 0x96699669, 0x69966996}, \ + {0x0000ffff, 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000, 0x0000ffff, 0x0000ffff, 0xffff0000}, \ + {0xaaaa5555, 0x5555aaaa, 0x5555aaaa, 0xaaaa5555, 0x5555aaaa, 0xaaaa5555, 0xaaaa5555, 0x5555aaaa}, \ + {0xcccc3333, 0x3333cccc, 0x3333cccc, 0xcccc3333, 0x3333cccc, 0xcccc3333, 0xcccc3333, 0x3333cccc}, \ + {0x66669999, 0x99996666, 0x99996666, 0x66669999, 0x99996666, 0x66669999, 0x66669999, 0x99996666}, \ + {0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0}, \ + {0x5a5aa5a5, 0xa5a55a5a, 0xa5a55a5a, 0x5a5aa5a5, 0xa5a55a5a, 0x5a5aa5a5, 0x5a5aa5a5, 0xa5a55a5a}, \ + {0x3c3cc3c3, 0xc3c33c3c, 0xc3c33c3c, 0x3c3cc3c3, 0xc3c33c3c, 0x3c3cc3c3, 0x3c3cc3c3, 0xc3c33c3c}, \ + {0x96966969, 0x69699696, 0x69699696, 0x96966969, 0x69699696, 0x96966969, 0x96966969, 0x69699696}, \ + {0xff0000ff, 0x00ffff00, 0x00ffff00, 0xff0000ff, 0x00ffff00, 0xff0000ff, 0xff0000ff, 0x00ffff00}, \ + {0x55aaaa55, 0xaa5555aa, 0xaa5555aa, 0x55aaaa55, 0xaa5555aa, 0x55aaaa55, 0x55aaaa55, 0xaa5555aa}, \ + {0x33cccc33, 0xcc3333cc, 0xcc3333cc, 0x33cccc33, 0xcc3333cc, 0x33cccc33, 0x33cccc33, 0xcc3333cc}, \ + {0x99666699, 0x66999966, 0x66999966, 0x99666699, 0x66999966, 0x99666699, 0x99666699, 0x66999966}, \ + {0x0ff0f00f, 0xf00f0ff0, 0xf00f0ff0, 0x0ff0f00f, 0xf00f0ff0, 0x0ff0f00f, 0x0ff0f00f, 0xf00f0ff0}, \ + {0xa55a5aa5, 0x5aa5a55a, 0x5aa5a55a, 0xa55a5aa5, 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a}, \ + {0xc33c3cc3, 0x3cc3c33c, 0x3cc3c33c, 0xc33c3cc3, 0x3cc3c33c, 0xc33c3cc3, 0xc33c3cc3, 0x3cc3c33c}, \ + {0x69969669, 0x96696996, 0x96696996, 0x69969669, 0x96696996, 0x69969669, 0x69969669, 0x96696996} }; + + +static void readCodeWords(uint64_t** codewords) { + uint32_t i, j, k; + for(i = 0; i < m_nCodewords; i++) { + for(j = 0; j < (m_nCWIntlen * sizeof(uint32_t)) / sizeof(uint64_t); j++) { + codewords[i][j] = 0; + for(k = 0; k < sizeof(uint64_t) / sizeof(uint32_t); k++) { + codewords[i][j] |= (((REGISTER_SIZE) CODE_MATRIX[i][j*sizeof(REGISTER_SIZE) / sizeof(uint32_t)+k]) << (k * 8 * sizeof(uint32_t))); + //cout << (hex) << CODE_MATRIX[i][j*2+k]; + } + // cout << (hex) << codewords[i][j] << ", "; + } + //cout << endl; + } +} + +#endif //CODEWORDS_H_ diff --git a/src/util/connection.cpp b/src/util/connection.cpp new file mode 100644 index 0000000..d14649c --- /dev/null +++ b/src/util/connection.cpp @@ -0,0 +1,78 @@ +/* + * connection.cpp + * + * Created on: Mar 7, 2013 + * Author: mzohner + */ + +#include "connection.h" + +bool connect(const char* address, uint16_t port, CSocket& sockfd) { + uint64_t lTO = CONNECT_TIMEO_MILISEC; +#ifdef DEBUG + cout << "Connecting to " << address << ": " << port << endl; +#endif + for( uint32_t i=0; i + +bool connect(const char* address, uint16_t port, CSocket& sockfd); +bool listen(const char* address, uint16_t port, CSocket* sockfd, uint32_t nconnections); + +#define RETRY_CONNECT 1000 +#define CONNECT_TIMEO_MILISEC 10000 + + +#endif diff --git a/src/util/crypto/crypto.cpp b/src/util/crypto/crypto.cpp new file mode 100644 index 0000000..d3964db --- /dev/null +++ b/src/util/crypto/crypto.cpp @@ -0,0 +1,409 @@ +/* + * crypto.cpp + * + * Created on: Jul 9, 2014 + * Author: mzohner + */ + + +#include "crypto.h" + +crypto::crypto(uint32_t symsecbits, uint8_t* seed) { + init(symsecbits, seed); +} + +crypto::crypto(uint32_t symsecbits) { + uint8_t* seed = (uint8_t*) malloc(sizeof(uint8_t) * AES_BYTES); + gen_secure_random(seed, AES_BYTES); + + init(symsecbits, seed); + free(seed); +} + +crypto::~crypto() { + free_prf_state(&global_prf_state); + free(aes_hash_in_buf); + free(aes_hash_out_buf); + free(sha_hash_buf); + free(aes_hash_buf_y1); + free(aes_hash_buf_y2); + //TODO: securely delete the AES keys +} + + +void crypto::init(uint32_t symsecbits, uint8_t* seed) { + //seed_aes_key(&(global_prf_state.aes_key), seed); + secparam = get_sec_lvl(symsecbits); + //aes_hash_key = NULL; + //aes_enc_key = NULL; + + //rndctr = (uint64_t*) calloc(ceil_divide(AES_BYTES, sizeof(uint64_t)), sizeof(uint64_t)); + init_prf_state(&global_prf_state, seed); + + aes_hash_in_buf = (uint8_t*) malloc(AES_BYTES); + aes_hash_out_buf = (uint8_t*) malloc(AES_BYTES); + aes_hash_buf_y1 = (uint8_t*) malloc(AES_BYTES); + aes_hash_buf_y2 = (uint8_t*) malloc(AES_BYTES); + + sha_hash_buf = (uint8_t*) malloc((secparam.symbits >> 3 ) * 2); + + if(secparam.symbits == ST.symbits) { + hash_routine = &sha1_hash; + } else if(secparam.symbits == MT.symbits) { + hash_routine = &sha256_hash; + } else if(secparam.symbits == LT.symbits) { + hash_routine = &sha256_hash; + } else if(secparam.symbits == XLT.symbits) { + hash_routine = &sha512_hash; + } else if(secparam.symbits == XXLT.symbits) { + hash_routine = &sha512_hash; + } else { + hash_routine = &sha256_hash; + } +} + +pk_crypto* crypto::gen_field(field_type ftype) { + uint8_t* pkseed = (uint8_t*) malloc(sizeof(uint8_t) * (secparam.symbits >> 3)); + gen_rnd(pkseed, secparam.symbits>>3); + if(ftype == P_FIELD) return new prime_field(secparam, pkseed); + else return new ecc_field(secparam, pkseed); +} + +void gen_rnd_bytes(prf_state_ctx* prf_state, uint8_t* resbuf, uint32_t nbytes) { + AES_KEY_CTX* aes_key; + uint64_t* rndctr; + uint8_t* tmpbuf; + uint32_t i, size; + int32_t dummy; + + aes_key = &(prf_state->aes_key); + rndctr = prf_state->ctr; + size = ceil_divide(nbytes, AES_BYTES); + tmpbuf = (uint8_t*) malloc(sizeof(uint8_t) * size * AES_BYTES); + + //TODO it might be better to store the result directly in resbuf but this would require the invoking routine to pad it to a multiple of AES_BYTES + for(i = 0; i < size; i++, rndctr[0]++) { + EVP_EncryptUpdate(aes_key, tmpbuf + i*AES_BYTES, &dummy, (uint8_t*) rndctr, AES_BYTES); + } + + memcpy(resbuf, tmpbuf, nbytes); + + free(tmpbuf); +} + +void crypto::gen_rnd(uint8_t* resbuf, uint32_t nbytes) { + gen_rnd_bytes(&global_prf_state, resbuf, nbytes); + /*uint8_t* tmpbuf; + uint32_t i; + int32_t dummy; + + uint32_t size = ceil_divide(nbytes, AES_BYTES); + + //TODO it might be better to store the result directly in resbuf but this would require the invoking routine to pad it to a multiple of AES_BYTES + tmpbuf = (uint8_t*) malloc(sizeof(uint8_t) * size * AES_BYTES); + for(i = 0; i < size; i++, rndctr[0]++) { + EVP_EncryptUpdate(&aes_rnd_key, tmpbuf + i*AES_BYTES, &dummy, (uint8_t*) rndctr, AES_BYTES); + } + + memcpy(resbuf, tmpbuf, nbytes); + + free(tmpbuf);*/ +} + + + + +void crypto::gen_rnd_uniform(uint8_t* resbuf, uint64_t mod) { + //TODO: implement +} + +void crypto::encrypt(AES_KEY_CTX* enc_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes) { + int32_t dummy; + EVP_EncryptUpdate(enc_key, resbuf, &dummy, inbuf, ninbytes); + //EVP_EncryptFinal_ex(enc_key, resbuf, &dummy); +} +void crypto::decrypt(AES_KEY_CTX* dec_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes) { + int32_t dummy; + //cout << "inbuf = " << (hex) << ((uint64_t*) inbuf)[0] << ((uint64_t*) inbuf)[1] << (dec) << endl; + EVP_DecryptUpdate(dec_key, resbuf, &dummy, inbuf, ninbytes); + //EVP_DecryptFinal_ex(dec_key, resbuf, &dummy); + //cout << "outbuf = " << (hex) << ((uint64_t*) resbuf)[0] << ((uint64_t*) resbuf)[1] << (dec) << " (" << dummy << ")" << endl; +} + +void crypto::encrypt(uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes) { + encrypt(&aes_enc_key, resbuf, inbuf, ninbytes); +} + + +void crypto::decrypt(uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes) { + decrypt(&aes_dec_key, resbuf, inbuf, ninbytes); +} + +void crypto::seed_aes_hash(uint8_t* seed, bc_mode mode, const uint8_t* iv) { + seed_aes_key(&aes_hash_key, seed, mode, iv); +} + +void crypto::seed_aes_enc(uint8_t* seed, bc_mode mode, const uint8_t* iv) { + seed_aes_key(&aes_enc_key, seed, mode, iv, true); + seed_aes_key(&aes_dec_key, seed, mode, iv, false); +} + +void crypto::init_aes_key(AES_KEY_CTX* aes_key, uint8_t* seed, bc_mode mode, const uint8_t* iv) { + seed_aes_key(aes_key, seed, mode, iv); +} + +void crypto::init_aes_key(AES_KEY_CTX* aes_key, uint32_t symbits, uint8_t* seed, bc_mode mode, const uint8_t* iv) { + seed_aes_key(aes_key, symbits, seed, mode, iv); +} + +void crypto::seed_aes_key(AES_KEY_CTX* aeskey, uint8_t* seed, bc_mode mode, const uint8_t* iv, bool encrypt) { + seed_aes_key(aeskey, secparam.symbits, seed, mode, iv, encrypt); +} + + +void crypto::seed_aes_key(AES_KEY_CTX* aeskey, uint32_t symbits, uint8_t* seed, bc_mode mode, const uint8_t* iv, bool encrypt) { + //*aeskey = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX)); + EVP_CIPHER_CTX_init(aeskey); + int (*initfct)(EVP_CIPHER_CTX*,const EVP_CIPHER*, ENGINE*, + const unsigned char*, const unsigned char*); + + if(encrypt) + initfct = EVP_EncryptInit_ex; + else + initfct = EVP_DecryptInit_ex; + + switch (mode) { + case ECB: + if(symbits <= 128) { + initfct(aeskey, EVP_aes_128_ecb(), NULL, seed, iv); + } else { + initfct(aeskey, EVP_aes_256_ecb(), NULL, seed, iv); + } + break; + case CBC: //ECB_ENC + if(symbits <= 128) { + initfct(aeskey, EVP_aes_128_cbc(), NULL, seed, iv); + } else { + initfct(aeskey, EVP_aes_256_cbc(), NULL, seed, iv); + } + break; + default: + if(symbits <= 128) { + initfct(aeskey, EVP_aes_128_ecb(), NULL, seed, iv); + } else { + initfct(aeskey, EVP_aes_256_ecb(), NULL, seed, iv); + } + break; + } +} + + + +void crypto::hash_ctr(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint32_t ctr) { + uint8_t* tmpbuf = (uint8_t*) malloc(ninbytes + sizeof(uint32_t)); + memcpy(tmpbuf, &ctr, sizeof(uint32_t)); + memcpy(tmpbuf + sizeof(uint32_t), inbuf, ninbytes); + hash_routine(resbuf, noutbytes, inbuf, ninbytes, sha_hash_buf); + free(tmpbuf); +} + + +void crypto::hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes) { + hash_routine(resbuf, noutbytes, inbuf, ninbytes, sha_hash_buf); +} + + +//A fixed-key hashing scheme that uses AES, should not be used for real hashing, hashes to AES_BYTES bytes +void crypto::fixed_key_aes_hash(AES_KEY_CTX* aes_key, uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes) { + uint32_t i; + int32_t dummy; + + //assert(aes_hash_key != NULL); + + memset(aes_hash_in_buf, 0, AES_BYTES); + memcpy(aes_hash_in_buf, inbuf, ninbytes); + + //two encryption iterations TODO: not secure since both blocks are treated independently, implement DM or MMO + EVP_EncryptUpdate(aes_key, aes_hash_out_buf, &dummy, aes_hash_in_buf, AES_BYTES); + + ((uint64_t*) aes_hash_out_buf)[0] ^= ((uint64_t*) aes_hash_in_buf)[0]; + ((uint64_t*) aes_hash_out_buf)[1] ^= ((uint64_t*) aes_hash_in_buf)[1]; + + memcpy(resbuf, aes_hash_out_buf, noutbytes); +} + +//An aes hashing scheme that takes as input a counter and an aes-key-struct, should not be used for real hashing +void crypto::aes_cbc_hash(AES_KEY_CTX* aes_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes) { + uint32_t i; + int32_t dummy; + + EVP_EncryptUpdate(aes_key, resbuf, &dummy, inbuf, ninbytes); + + //TODO: optimized for faster PSI, input is always size of 32-bytes + for(i = 0; i < ninbytes/AES_BYTES; i++) { + ((uint64_t*) resbuf)[0] ^= ((uint64_t*) inbuf)[2*i]; + ((uint64_t*) resbuf)[1] ^= ((uint64_t*) inbuf)[2*i+1]; + } + //for(i = 0; i < ninbytes; i++) { + // resbuf[i] ^= inbuf[i]; + //} +} + +//Generate a random permutation of neles elements using Knuths algorithm +void crypto::gen_rnd_perm(uint32_t* perm, uint32_t neles) { + uint32_t* rndbuf = (uint32_t*) malloc(sizeof(uint32_t) * neles); + uint32_t i, j; + //TODO Generate random numbers (CAREFUL: NOT UNIFORM) + gen_rnd((uint8_t*) rndbuf, sizeof(uint32_t) * neles); + for(i = 0; i < neles; i++) { + perm[i] = i; + } + for(i = 0; i < neles; i++) { + j = rndbuf[i] % neles; //NOT UNIFORM + swap(perm[i], perm[j]); + } + free(rndbuf); +} + +uint32_t crypto::get_aes_key_bytes() { + if(secparam.symbits == ST.symbits) return 16; + else if(secparam.symbits == MT.symbits) return 16; + else if(secparam.symbits == LT.symbits) return 16; + else if(secparam.symbits == XLT.symbits) return 24; + else if(secparam.symbits == XXLT.symbits) return 32; + else return 64; +} + +uint32_t crypto::get_hash_bytes() { + if(secparam.symbits == ST.symbits) return 20; + else if(secparam.symbits == MT.symbits) return 32; + else if(secparam.symbits == LT.symbits) return 32; + else if(secparam.symbits == XLT.symbits) return 64; + else if(secparam.symbits == XXLT.symbits) return 64; + else return 64; +} + +//Generate a common seed, is only secure in the semi-honest model +void crypto::gen_common_seed(prf_state_ctx* prf_state, CSocket& sock) { + uint8_t *seed_buf, *seed_rcv_buf; + uint32_t seed_bytes, i; + + seed_bytes = get_aes_key_bytes(); + seed_buf = (uint8_t*) malloc(seed_bytes); + seed_rcv_buf = (uint8_t*) malloc(seed_bytes); + + //randomly generate and exchange seed bytes: + gen_rnd(seed_buf, seed_bytes); + sock.Send(seed_buf, seed_bytes); + sock.Receive(seed_rcv_buf, seed_bytes); + + //xor both seeds + for(i = 0; i < seed_bytes; i++) { + seed_buf[i] ^= seed_rcv_buf[i]; + } + + init_prf_state(prf_state, seed_buf); + + free(seed_buf); + free(seed_rcv_buf); +} + +void crypto::init_prf_state(prf_state_ctx* prf_state, uint8_t* seed) { + seed_aes_key(&(prf_state->aes_key), seed); + prf_state->ctr = (uint64_t*) calloc(ceil_divide(secparam.symbits, 8*sizeof(uint64_t)), sizeof(uint64_t)); +} + +void crypto::free_prf_state(prf_state_ctx* prf_state) { + free(prf_state->ctr); + //TODO: delete the AES key +} + + +void sha1_hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint8_t* hash_buf) { + SHA_CTX sha; + SHA1_Init(&sha); + SHA1_Update(&sha, inbuf, ninbytes); + SHA1_Final(hash_buf, &sha); + memcpy(resbuf, hash_buf, noutbytes); +} + +void sha256_hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint8_t* hash_buf) { + SHA256_CTX sha; + SHA256_Init(&sha); + SHA256_Update(&sha, inbuf, ninbytes); + SHA256_Final(hash_buf, &sha); + memcpy(resbuf, hash_buf, noutbytes); +} + +void sha512_hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint8_t* hash_buf) { + SHA512_CTX sha; + SHA512_Init(&sha); + SHA512_Update(&sha, inbuf, ninbytes); + SHA512_Final(hash_buf, &sha); + memcpy(resbuf, hash_buf, noutbytes); +} + +//Read random bytes from /dev/random - copied from stackoverflow (post by zneak) +void gen_secure_random(uint8_t* dest, uint32_t nbytes) { + int32_t randomData = open("/dev/random", O_RDONLY); + uint32_t bytectr = 0; + while (bytectr < nbytes) { + uint32_t result = read(randomData, dest + bytectr, nbytes - bytectr); + if (result < 0) { + cerr << "Unable to read from /dev/random, exiting" << endl; + exit(0); + } + bytectr += result; + } + close(randomData); +} + +seclvl get_sec_lvl(uint32_t symsecbits) { + if(symsecbits == ST.symbits) return ST; + else if(symsecbits == MT.symbits) return MT; + else if(symsecbits == LT.symbits) return LT; + else if(symsecbits == XLT.symbits) return XLT; + else if(symsecbits == XXLT.symbits) return XXLT; + else return LT; +} + +void crypto::aes_compression_hash(AES_KEY_CTX* aes_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes) { + int32_t dummy; + + ((uint64_t*) aes_hash_in_buf)[0] = ((uint64_t*) inbuf)[0] ^ ((uint64_t*) inbuf)[2]; + ((uint64_t*) aes_hash_in_buf)[1] = ((uint64_t*) inbuf)[1] ^ ((uint64_t*) inbuf)[3]; + + EVP_EncryptUpdate(aes_key, aes_hash_buf_y1, &dummy, aes_hash_in_buf, AES_BYTES); + + //cout << (hex) << ((uint64_t*) aes_hash_buf_y1)[0] << ((uint64_t*) aes_hash_buf_y1)[1] << (dec) << endl; + + ((uint64_t*) aes_hash_in_buf)[0] = ((uint64_t*) inbuf)[0] ^ ((uint64_t*) inbuf)[2] ^ ((uint64_t*) aes_hash_buf_y1)[0]; + ((uint64_t*) aes_hash_in_buf)[1] = ((uint64_t*) inbuf)[1] ^ ((uint64_t*) inbuf)[3] ^ ((uint64_t*) aes_hash_buf_y1)[1]; + + EVP_EncryptUpdate(aes_key, aes_hash_buf_y2, &dummy, aes_hash_in_buf, AES_BYTES); + + //cout << (hex) << ((uint64_t*) aes_hash_buf_y2)[0] << ((uint64_t*) aes_hash_buf_y2)[1] << (dec) << endl; + + ((uint64_t*) aes_hash_in_buf)[0] = ((uint64_t*) inbuf)[0] ^ ((uint64_t*) inbuf)[2] ^ ((uint64_t*) aes_hash_buf_y2)[0]; + ((uint64_t*) aes_hash_in_buf)[1] = ((uint64_t*) inbuf)[1] ^ ((uint64_t*) inbuf)[3] ^ ((uint64_t*) aes_hash_buf_y2)[1]; + + EVP_EncryptUpdate(aes_key, resbuf, &dummy, aes_hash_in_buf, AES_BYTES); + + //cout << (hex) << ((uint64_t*) resbuf)[0] << ((uint64_t*) resbuf)[1] << (dec) << endl; + + ((uint64_t*) resbuf)[0] = ((uint64_t*) inbuf)[0] ^ ((uint64_t*) aes_hash_buf_y1)[0] ^ ((uint64_t*) aes_hash_buf_y2)[0] ^ ((uint64_t*) resbuf)[0]; + ((uint64_t*) resbuf)[1] = ((uint64_t*) inbuf)[1] ^ ((uint64_t*) aes_hash_buf_y1)[1] ^ ((uint64_t*) aes_hash_buf_y2)[1] ^ ((uint64_t*) resbuf)[1]; +} + + + + +/*static void InitAndReadCodeWord(REGISTER_SIZE*** codewords) { + uint32_t ncodewords = m_nCodeWordBits; + uint32_t ncwintlen = 8; + *codewords = (REGISTER_SIZE**) malloc(sizeof(REGISTER_SIZE*) * ncodewords); + for(uint32_t i = 0; i < m_nCodewords; i++) { + (*codewords)[i] = (REGISTER_SIZE*) malloc(sizeof(REGISTER_SIZE) * ((ncwintlen * sizeof(uint32_t)) / sizeof(REGISTER_SIZE))); + } + readCodeWords(*codewords); +}*/ diff --git a/src/util/crypto/crypto.h b/src/util/crypto/crypto.h new file mode 100644 index 0000000..ace7cb8 --- /dev/null +++ b/src/util/crypto/crypto.h @@ -0,0 +1,139 @@ +/* + * crypto.h + * + * Created on: Jul 9, 2014 + * Author: mzohner + */ + +#ifndef CRYPTO_H_ +#define CRYPTO_H_ + +#include +#include +#include +#include +#include + +#include "../typedefs.h" +#include "pk-crypto.h" +#include "gmp-pk-crypto.h" +#include "ecc-pk-crypto.h" +#include "../codewords.h" +#include "../socket.h" + + +#define AES_BYTES 16 +#define AES_BITS AES_BYTES*8 + +const uint8_t ZERO_IV[AES_BYTES]={0}; + +const uint8_t const_seed[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; + + + +enum bc_mode {ECB, CBC}; + +typedef EVP_CIPHER_CTX AES_KEY_CTX; + +struct prf_state_ctx { + AES_KEY_CTX aes_key; + uint64_t* ctr; +}; + + +//TODO: not thread-secure when multiple threads generate random data +class crypto { + +public: + + crypto(uint32_t symsecbits, uint8_t* seed); + crypto(uint32_t symsecbits); + ~crypto(); + + //Randomness generation routines + void gen_rnd(uint8_t* resbuf, uint32_t numbytes); + //void gen_rnd(prf_state_ctx* prf_state, uint8_t* resbuf, uint32_t nbytes); + void gen_rnd_uniform(uint8_t* resbuf, uint64_t mod); + void gen_rnd_perm(uint32_t* perm, uint32_t neles); + + //Encryption routines + void encrypt(uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes); + void decrypt(uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes); + + //Hash routines + void hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes); + void hash_ctr(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint32_t ctr); + void fixed_key_aes_hash(AES_KEY_CTX* aes_key, uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes); + void fixed_key_aes_hash_ctr(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes); + + void aes_cbc_hash(AES_KEY_CTX* aes_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes); + void aes_compression_hash(AES_KEY_CTX* aes_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes); + + + //Key seed routines + void seed_aes_hash(uint8_t* seed, bc_mode mode=ECB, const uint8_t* iv=ZERO_IV); + void seed_aes_enc(uint8_t* seed, bc_mode mode=ECB, const uint8_t* iv=ZERO_IV); + + //External encryption routines + void init_aes_key(AES_KEY_CTX* aes_key, uint8_t* seed, bc_mode mode=ECB, const uint8_t* iv=ZERO_IV); + void init_aes_key(AES_KEY_CTX* aes_key, uint32_t symbits, uint8_t* seed, bc_mode mode=ECB, const uint8_t* iv=ZERO_IV); + uint32_t get_aes_key_bytes(); + void encrypt(AES_KEY_CTX* enc_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes); + void decrypt(AES_KEY_CTX* dec_key, uint8_t* resbuf, uint8_t* inbuf, uint32_t ninbytes); + + pk_crypto* gen_field(field_type ftype); + + seclvl get_seclvl() {return secparam;}; + uint32_t get_hash_bytes(); + + void gen_common_seed(prf_state_ctx* aes_key, CSocket& sock); +private: + void seed_aes_key(AES_KEY_CTX* aeskey, uint8_t* seed, bc_mode mode=ECB, const uint8_t* iv=ZERO_IV, bool encrypt=true); + void seed_aes_key(AES_KEY_CTX* aeskey, uint32_t symseclvl, uint8_t* seed, bc_mode mode=ECB, const uint8_t* iv=ZERO_IV, bool encrypt=true); + void init(uint32_t symsecbits, uint8_t* seed); + void init_prf_state(prf_state_ctx* prf_state, uint8_t* seed); + void free_prf_state(prf_state_ctx* prf_state); + + AES_KEY_CTX aes_hash_key; + AES_KEY_CTX aes_enc_key; + AES_KEY_CTX aes_dec_key; + prf_state_ctx global_prf_state; + //AES_KEY_CTX aes_rnd_key; + + seclvl secparam; + //uint64_t* rndctr; + uint8_t* aes_hash_in_buf; + uint8_t* aes_hash_out_buf; + uint8_t* aes_hash_buf_y1; + uint8_t* aes_hash_buf_y2; + + uint8_t* sha_hash_buf; + + void (*hash_routine)(uint8_t*, uint32_t, uint8_t*, uint32_t, uint8_t*); +}; + + +//Some functions that should be useable without the class +void sha1_hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint8_t* hash_buf); +void sha256_hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint8_t* hash_buf); +void sha512_hash(uint8_t* resbuf, uint32_t noutbytes, uint8_t* inbuf, uint32_t ninbytes, uint8_t* hash_buf); +void gen_secure_random(uint8_t* dest, uint32_t nbytes); +void gen_rnd_bytes(prf_state_ctx* prf_state, uint8_t* resbuf, uint32_t nbytes); + +seclvl get_sec_lvl(uint32_t symsecbits); + +static const uint32_t m_nCodeWordBits = 256; +static const uint32_t m_nCodeWordBytes = m_nCodeWordBits/8; + +static void InitAndReadCodeWord(REGISTER_SIZE*** codewords) { + uint32_t ncodewords = m_nCodeWordBits; + uint32_t ncwintlen = 8; + *codewords = (REGISTER_SIZE**) malloc(sizeof(REGISTER_SIZE*) * ncodewords); + for(uint32_t i = 0; i < m_nCodewords; i++) { + (*codewords)[i] = (REGISTER_SIZE*) malloc(sizeof(REGISTER_SIZE) * ((ncwintlen * sizeof(uint32_t)) / sizeof(REGISTER_SIZE))); + } + readCodeWords(*codewords); +} + + +#endif /* CRYPTO_H_ */ diff --git a/src/util/crypto/ecc-pk-crypto.cpp b/src/util/crypto/ecc-pk-crypto.cpp new file mode 100644 index 0000000..4ea7f12 --- /dev/null +++ b/src/util/crypto/ecc-pk-crypto.cpp @@ -0,0 +1,289 @@ +/* + * ecc-pk-crypto.cpp + * + * Created on: Jul 11, 2014 + * Author: mzohner + */ + +#include "ecc-pk-crypto.h" + + +char *ecx163 = (char *) "2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8"; +char *ecy163 = (char *) "289070fb05d38ff58321f2e800536d538ccdaa3d9"; + +char *ecx233 = (char *) "17232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126"; +char *ecy233 = (char *) "1db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3"; + +char *ecx283 = (char *) "503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836"; +char *ecy283 = (char *) "1ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259"; + + + +void ecc_field::init(seclvl sp, uint8_t* seed) { + + miracl *mip = mirsys(sp.ecckcbits, 2); + fparams = (ecc_fparams*) malloc(sizeof(ecc_fparams)); + secparam = sp; + + //miracl *mip=mirsys(MR_ROUNDUP(abs(163),4),16); + char *ecp = NULL, *ecb = NULL, *ecx = ecx163, *ecy = ecy163; + fparams->BB = new Big(); + fparams->BA = new Big(); + fparams->BP = new Big(); + + + if(secparam.ecckcbits == ST.ecckcbits) { + ecx = ecx163; ecy = ecy163; fparams->m = 163; fparams->a = 7; + fparams->b = 6; fparams->c = 3; *fparams->BA = 1; fparams->secparam = ST.ecckcbits; + } else if(secparam.ecckcbits == MT.ecckcbits) { + ecx = ecx233; ecy = ecy233; fparams->m = 233; fparams->a = 74; + fparams->b = 0; fparams->c = 0; *fparams->BA = 0; fparams->secparam = MT.ecckcbits; + } else if(secparam.ecckcbits == LT.ecckcbits) { + ecx = ecx283; ecy = ecy283; fparams->m = 283; fparams->a = 12; + fparams->b = 7; fparams->c = 5; *fparams->BA = 0; fparams->secparam = LT.ecckcbits; + } else { //Long term security + ecx = ecx283; ecy = ecy283; fparams->m = 283; fparams->a = 12; + fparams->b = 7; fparams->c = 5; *fparams->BA = 0; fparams->secparam = LT.ecckcbits; + } + + //seed the miracl rnd generator + irand((long)(*seed)); + + //Change the base to read in the parameters + mip->IOBASE = 16; + *fparams->BB = 1; + + ecurve2_init(fparams->m, fparams->a, fparams->b, fparams->c, + fparams->BA->getbig(), fparams->BB->getbig(), false, MR_BEST); + + fparams->X = new Big(); + fparams->Y = new Big(); + *fparams->X = ecx; + *fparams->Y = ecy; + + //For ECC, a coordinate is transferred as well as a 1/-1 + fe_bytelen = ceil_divide(secparam.ecckcbits,8) + 1; + + mip->IOBASE = 16; +} + +ecc_field::~ecc_field(){ + delete fparams->Y; + delete fparams->X; + delete fparams->BA; + delete fparams->BB; + delete fparams->BP; + + free(fparams); + + mirexit(); +} + + +num* ecc_field::get_num() { + return new ecc_num(this); +} + +num* ecc_field::get_rnd_num(uint32_t bitlen) { + Big ele; + if(bitlen == 0) + bitlen = secparam.ecckcbits; + ele = rand(bitlen, 2); + return new ecc_num(this, &ele); +} +fe* ecc_field::get_fe() { + return new ecc_fe(this); +} + +fe* ecc_field::get_rnd_fe(uint32_t bitlen) { + return sample_random_point(); +} + +fe* ecc_field::get_generator() { + EC2 g = EC2(*fparams->X, *fparams->Y); + return new ecc_fe(this, &g); +} +fe* ecc_field::get_rnd_generator() { + return sample_random_point(); +} +brickexp* ecc_field::get_brick(fe* gen) { + return new ecc_brickexp(gen, fparams); +} +uint32_t ecc_field::get_size() { + return secparam.ecckcbits; +} + +fe* ecc_field::sample_random_point() { + Big bigtmp; + EC2 point; + uint32_t itmp = rand()%2; + do + { + bigtmp = rand(secparam.symbits, 2); + point = EC2(bigtmp, itmp); + } + while (point_at_infinity(point.get_point())); + return new ecc_fe(this, &point); +} + + + + +ecc_fe::ecc_fe(ecc_field* fld) { + field = fld; + init(); +} + +ecc_fe::ecc_fe(ecc_field* fld, EC2* src) { + field = fld; + init(); + *val = *src; +} +ecc_fe::~ecc_fe() { + delete val; +} + +void ecc_fe::set(fe* src) { + *val = *fe2ec2(src); +} +EC2* ecc_fe::get_val() { + return val; +} + +void ecc_fe::set_mul(fe* a, fe* b) { + set(a); + (*val)+=(*fe2ec2(b)); +} + +void ecc_fe::set_pow(fe* b, num* e) { + set(b); + (*val)*=(*num2Big(e)); +} + +void ecc_fe::set_div(fe* a, fe* b) { + set(a); + (*val)-=(*fe2ec2(b)); +} + +void ecc_fe::set_double_pow_mul(fe* b1, num* e1, fe* b2, num* e2) { + ecurve2_mult2(num2Big(e1)->getbig(), fe2ec2(b1)->get_point(), num2Big(e2)->getbig(), fe2ec2(b2)->get_point(), val->get_point()); +} + +void ecc_fe::import_from_bytes(uint8_t* buf) { + byte_to_point(val, field->fe_byte_size(), buf); +} +//export and pad all leading zeros +void ecc_fe::export_to_bytes(uint8_t* buf) { + point_to_byte(buf, field->fe_byte_size(), val); +} + +void ecc_fe::sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen) { + EC2 point; + Big bigtmp; + uint8_t* tmpbuf = (uint8_t*) calloc(bytelen + 1, sizeof(uint8_t)); + memcpy(tmpbuf+1, buf, bytelen); + bytes_to_big (bytelen, (const char*) tmpbuf, bigtmp.getbig()); + premult(bigtmp.getbig(), MAXMSGSAMPLE, bigtmp.getbig()); + for(int i = 0; i < MAXMSGSAMPLE; i++) + { + point = EC2(bigtmp, 0); + if(!point_at_infinity(point.get_point())) { + *val = point; + return; + } + point = EC2(bigtmp, 1); + if(!point_at_infinity(point.get_point())) { + *val = point; + return; + } + incr(bigtmp.getbig(), 1, bigtmp.getbig()); + } + cerr << "Error while sampling point, exiting!" << endl; + exit(0); +} + + + + +ecc_num::ecc_num(ecc_field* fld) { + field = fld; + val = new Big(); +} +ecc_num::ecc_num(ecc_field* fld, Big* src) { + field = fld; + val = new Big(); + copy(src->getbig(), val->getbig()); +} + +ecc_num::~ecc_num() { + delete val; +} + +Big* ecc_num::get_val() { + return val; +} + +void ecc_num::set(num* src) { + copy(((ecc_num*) src)->get_val()->getbig(), val->getbig()); +} +void ecc_num::set_si(int32_t src) { + convert(src, val->getbig()); +} +void ecc_num::set_add(num* a, num* b) { + add(((ecc_num*) a)->get_val()->getbig(), ((ecc_num*) b)->get_val()->getbig(), val->getbig()); +} +void ecc_num::set_mul(num* a, num* b) { + multiply(((ecc_num*) a)->get_val()->getbig(), ((ecc_num*) b)->get_val()->getbig(), val->getbig()); +} + +void ecc_num::import_from_bytes(uint8_t* buf, uint32_t field_size_bytes) { + bytes_to_big (field_size_bytes, (const char*) buf, val->getbig()); +} + +//export and pad all leading zeros +void ecc_num::export_to_bytes(uint8_t* buf, uint32_t field_size_bytes) { + big_to_bytes ((int32_t) field_size_bytes, val->getbig(), (char*) buf, true); +} + + + +// ecc_brickexp methods +ecc_brickexp::ecc_brickexp(fe* point, ecc_fparams* fparams) { + Big x, y; + fe2ec2(point)->getxy(x, y); + ebrick2_init(&br, x.getbig(), y.getbig(), fparams->BA->getbig(), fparams->BB->getbig(), + fparams->m, fparams->a, fparams->b, fparams->c, 8, fparams->secparam); +} + +void ecc_brickexp::pow(fe* result, num* e) +{ + Big xtmp, ytmp; + mul2_brick(&br, num2Big(e)->getbig(), xtmp.getbig(), ytmp.getbig()); + *fe2ec2(result) = EC2(xtmp, ytmp); +} + + +// general methods + +void byte_to_point(EC2 *point, uint32_t field_size_bytes, uint8_t* pBufIdx) { + uint32_t itmp; + Big bigtmp; + itmp = (uint32_t) (pBufIdx[0]); + + bytes_to_big(field_size_bytes-1, (const char*) (pBufIdx + 1), bigtmp.getbig()); + *point = EC2(bigtmp, itmp); +} + +void point_to_byte(uint8_t* pBufIdx, uint32_t field_size_bytes, EC2* point) { + uint32_t itmp; + Big bigtmp; + //compress to x-point and y-bit and convert to byte array + itmp = point->get(bigtmp); + + //first store the y-bit + pBufIdx[0] = (uint8_t) (itmp & 0x01); + + //then store the x-coordinate (sec-param/8 byte size) + big_to_bytes(field_size_bytes-1, bigtmp.getbig(), (char*) pBufIdx+1, true); + +} diff --git a/src/util/crypto/ecc-pk-crypto.h b/src/util/crypto/ecc-pk-crypto.h new file mode 100644 index 0000000..2adfda9 --- /dev/null +++ b/src/util/crypto/ecc-pk-crypto.h @@ -0,0 +1,143 @@ +/* + * ecc-pk-crypto.h + * + * Created on: Jul 11, 2014 + * Author: mzohner + */ + +#ifndef ECC_PK_CRYPTO_H_ +#define ECC_PK_CRYPTO_H_ + +#include "pk-crypto.h" + +#include "../../Miracl/ecn.h" +#include "../../Miracl/big.h" +#include "../../Miracl/ec2.h" + + +#define fe2ec2(fieldele) (((ecc_fe*) (fieldele))->get_val()) +#define num2Big(number) (((ecc_num*) (number))->get_val()) + +//how many repetitions of random point samplings should be performed +#define MAXMSGSAMPLE 256 + + +struct ecc_fparams { + Big* BA; + Big* BB; + Big* X; + Big* Y; + Big* BP; + int32_t m; + int32_t a; + int32_t b; + int32_t c; + uint32_t secparam; +}; + +class ecc_num; +class ecc_fe; +class ecc_brickexp; + +class ecc_field : public pk_crypto { +public: + ecc_field(seclvl sp, uint8_t* seed) : pk_crypto(sp, seed) {init(sp, seed);}; + ~ecc_field(); + + num* get_num(); + num* get_rnd_num(uint32_t bitlen=0); + fe* get_fe(); + fe* get_rnd_fe(uint32_t bitlen); + fe* get_generator(); + fe* get_rnd_generator(); + uint32_t get_size(); + //fe* sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen); + uint32_t num_byte_size() {return ceil_divide(secparam.ecckcbits, 8);} + uint32_t get_field_size() {return secparam.ecckcbits;}; + + brickexp* get_brick(fe* gen); + ecc_fparams* get_params() {return fparams;}; + + //#define SampleFieldElementFromBytes(ele, buf, bytelen) ByteToFieldElement(ele, bytelen, buf) + //#define FieldSampleRandomGenerator(g, div, params) SampleRandomGenerator(g, div, (¶ms)) +protected: + void init(seclvl sp, uint8_t* seed); +private: + fe* sample_random_point(); + /*Big* BA; + Big* BB; + Big* X; + Big* Y; + Big* BP; + int32_t m; + int32_t a; + int32_t b; + int32_t c;*/ + ecc_fparams* fparams; +}; + + + +class ecc_num : public num { + //This is a Big +public: + ecc_num(ecc_field* fld); + ecc_num(ecc_field* fld, Big* src); + ~ecc_num(); + void set(num* src); + void set_si(int32_t src); + void set_add(num* a, num* b); + void set_mul(num* a, num* b); + + Big* get_val(); + + void export_to_bytes(uint8_t* buf, uint32_t field_size_bytes); + void import_from_bytes(uint8_t* buf, uint32_t field_size_bytes); + void set_rnd(uint32_t bits); + void print() {cout << (*val) << endl;}; + +private: + Big* val; + ecc_field* field; +}; + + +class ecc_fe : public fe { +public: + ecc_fe(ecc_field* fld); + ecc_fe(ecc_field* fld, EC2* src); + ~ecc_fe(); + void set(fe* src); + EC2* get_val(); + void set_mul(fe* a, fe* b); + + void set_pow(fe* b, num* e); + void set_div(fe* a, fe* b); + void set_double_pow_mul(fe* b1, num* e1, fe* b2, num* e2); + void export_to_bytes(uint8_t* buf); + void import_from_bytes(uint8_t* buf); + void sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen); + + void print() {cout << (*val) << endl;}; + + +private: + void init() {val = new EC2();}; + EC2* val; + ecc_field* field; +}; + +class ecc_brickexp : public brickexp { +public: + ecc_brickexp(fe* point, ecc_fparams* fparams); + ~ecc_brickexp() {ebrick2_end(&br);} + + void pow(fe* res, num* e); +private: + ebrick2 br; +}; + +void point_to_byte(uint8_t* pBufIdx, uint32_t field_size_bytes, EC2* to_export); +void byte_to_point(EC2* to_export, uint32_t field_size_bytes, uint8_t* pBufIdx); + +#endif /* ECC_PK_CRYPTO_H_ */ diff --git a/src/util/crypto/gmp-pk-crypto.cpp b/src/util/crypto/gmp-pk-crypto.cpp new file mode 100644 index 0000000..5329b93 --- /dev/null +++ b/src/util/crypto/gmp-pk-crypto.cpp @@ -0,0 +1,280 @@ +/* + * gmp-pk-crypto.cpp + * + * Created on: Jul 11, 2014 + * Author: mzohner + */ + +#include "gmp-pk-crypto.h" + + + +//Parameters for different security levels +const char* ifcp1024 = + "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"; +const char* ifcg1024 = + "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"; +const char* ifcq1024 = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353"; + +const char* ifcp2048 = + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC2129037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708B3BF8A317091883681286130BC8985DB1602E714415D9330278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486DCDF93ACC44328387315D75E198C641A480CD86A1B9E587E8BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71CF9DE5384E71B81C0AC4DFFE0C10E64F"; +const char* ifcg2048 = + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFAAB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7C17669101999024AF4D027275AC1348BB8A762D0521BC98AE247150422EA1ED409939D54DA7460CDB5F6C6B250717CBEF180EB34118E98D119529A45D6F834566E3025E316A330EFBB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC017981BC087F2A7065B384B890D3191F2BFA"; +const char* ifcq2048 = + "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB"; + +const char* ifcp3072 = + "4660194093823565506151007332698542081380390944320667936220310340292682538415201463451360005469701273992420569531194415296871671272562243754789577412471203509686259933515539120145538889500684305065682267020422897056483203401642088590732633756278140548667640739272073464322452643609409839498807131787408915921523565001045685221279165409792825261753615641493423723165471868882028678262386826730035778207616806238910696112513243832793252430036079010833108716296401084350809152423357477416465451376967706115065572717893335336664895800189754170750266169252030669114411476002012410621336179123441424048589750501111541393610787337793314723136089502117079738181113934544472215273637670210480814609550715859453809706797176331069587697357167970759889883398852942449568449890603652456531060380065260476714266615239827983706919432589669744367350756821903843388105282430635020233707272521317674908786962912228887786913664926989228941514639"; +const char* ifcg3072 = + "326984479748743614358878489890111032378521682641889472728164592588245254735528952815040417677135099463681521117067228131302984716932197927691804537047698386112034189358693637764887258325546424576668654933254773228919028116187485325776123548207630122958160311311825230114818910264101591293903307807790394765896174615027850669640300925521032111542648598127663424462192520490917608209583615366128345913820058976254028107968965281721876376153097516948596625654797921929621363755081263164203185942482227411046415127689226121648774535224687708280963930985498313715804706762069594298539593719253724193098201932449349224692341850008449711165375995101343314201170357859203662648251088921851885444086613889195257606710405156897225917687758015354941738963422772322756212536951044725465040734436163477969317027796051497934165333064621979305683254912099909723895352817468375097484456065145582788954244042708099846989842764657922387568064"; +const char* ifcq3072 = + "95729504467608377623766753562217147614989054519467474668915026082895293552781"; + +gmp_num::gmp_num(prime_field* fld) { + field = fld; + mpz_init(val); +} +gmp_num::gmp_num(prime_field* fld, mpz_t src) { + field = fld; + mpz_init(val); + mpz_set(val, src); +} + +gmp_num::~gmp_num() { + mpz_clear(val); +} + +mpz_t* gmp_num::get_val() { + return &val; +} + +void gmp_num::set(num* src) { + mpz_set(val, *num2mpz(src)); +} +void gmp_num::set_si(int32_t src) { + mpz_set_si(val, src); +} +void gmp_num::set_add(num* a, num* b) { + mpz_add(val, *num2mpz(a), *num2mpz(b)); +} +void gmp_num::set_mul(num* a, num* b) { + mpz_mul(val, *num2mpz(a), *num2mpz(b)); +} + +void gmp_num::import_from_bytes(uint8_t* buf, uint32_t field_size) { + mpz_import(val, field_size, 1, sizeof((buf)[0]), 0, 0, (buf)); +} + +//export and pad all leading zeros +void gmp_num::export_to_bytes(uint8_t* buf, uint32_t field_size) { + mpz_export_padded(buf, ceil_divide(field_size, 8), val); +} + +num* prime_field::get_rnd_num(uint32_t bitlen) { + mpz_t val; + if(bitlen == 0) + bitlen = secparam.ifcbits; + mpz_init(val); + mpz_urandomm(val, rnd_state, q); //sample_rnd_mpz_t(val, bits, fp); + return new gmp_num(this, val); +} + +fe* prime_field::get_rnd_fe(uint32_t bitlen) { + mpz_t val; + mpz_init(val); + mpz_urandomm(val, rnd_state, q); //sample_rnd_mpz_t(val, bits, fp); + return new gmp_fe(this, val); +} + +gmp_fe::gmp_fe(prime_field* fld) { + field = fld; + init(); +} + +gmp_fe::gmp_fe(prime_field* fld, mpz_t src) { + field = fld; + init(); + mpz_set(val, src); +} +gmp_fe::~gmp_fe() { + mpz_clear(val); +} + +void gmp_fe::set(fe* src) { + mpz_set(val, *fe2mpz(src)); +} +mpz_t* gmp_fe::get_val() { + return &val; +} + +void gmp_fe::set_mul(fe* a, fe* b) { + mpz_mul(val, *fe2mpz(a), *fe2mpz(b)); + mpz_mod(val, val, *field->get_p()); +} + +void gmp_fe::set_pow(fe* b, num* e) { + mpz_powm(val, *fe2mpz(b), *num2mpz(e), *field->get_p()); +} + +void gmp_fe::set_div(fe* a, fe* b) { + mpz_invert(val, *fe2mpz(b), *field->get_p()); + mpz_mul(val, *fe2mpz(a), val); + mpz_mod(val, val, *field->get_p()); +} + +void gmp_fe::set_double_pow_mul(fe* b1, num* e1, fe* b2, num* e2) { + gmp_fe tmpa(field), tmpb(field); + tmpa.set_pow(b1, e1); //tmpa=b1^e1 + tmpb.set_pow(b2, e2); //tmpb=b2^e1 + set_mul(&tmpa, &tmpb); //val = b1^e1 * b2^e2 +} + +void gmp_fe::import_from_bytes(uint8_t* buf) { + mpz_import(val, field->fe_byte_size(), 1, sizeof((buf)[0]), 0, 0, (buf)); +} +//export and pad all leading zeros +void gmp_fe::export_to_bytes(uint8_t* buf) { + mpz_export_padded(buf, field->fe_byte_size(), val); +} + +void gmp_fe::sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen) { + mpz_import(val, bytelen, 1, sizeof((buf)[0]), 0, 0, (buf)); + mpz_mod(val, val, *field->get_p()); +} + + +num* prime_field::get_num() { + return new gmp_num(this); +} +fe* prime_field::get_fe() { + return new gmp_fe(this); +} +mpz_t* prime_field::get_p() { + return &p; +} +fe* prime_field::get_generator() { + return new gmp_fe(this, g); +} + +fe* prime_field::get_rnd_generator() { + mpz_t tmp; + mpz_init(tmp); + //sample random hi -- sample random element x in Zp, and then compute x^{(p-1)/q} mod p + do { + mpz_urandomb(tmp, rnd_state, secparam.ifcbits); + mpz_mod(tmp, tmp, p); + mpz_powm(tmp, tmp, q, p); + } while(!(mpz_cmp_ui(tmp, (uint32_t) 1) ) ); + return new gmp_fe(this, tmp); +} + +brickexp* prime_field::get_brick(fe* gen) { + return new gmp_brickexp(gen, this); +} + +uint32_t prime_field::get_size() { + return secparam.ifcbits; +} + +void prime_field::init(seclvl sp, uint8_t* seed) { + mpz_t rnd_seed; + + //TODO: change to inits if working correctly + mpz_init(p); + mpz_init(g); + mpz_init(q); + mpz_init(rnd_seed); + secparam = sp; + + mpz_import(rnd_seed, secparam.symbits, 1, sizeof((seed)[0]), 0, 0, seed); + + if (secparam.ifcbits == ST.ifcbits) { + mpz_set_str(p, ifcp1024, 16); + mpz_set_str(g, ifcg1024, 16); + mpz_set_str(q, ifcq1024, 16); + } else if (secparam.ifcbits == MT.ifcbits) { + mpz_set_str(p, ifcp2048, 16); + mpz_set_str(g, ifcg2048, 16); + mpz_set_str(q, ifcq2048, 16); + } else if (secparam.ifcbits == LT.ifcbits) { + mpz_set_str(p, ifcp3072, 10); + mpz_set_str(g, ifcg3072, 10); + mpz_set_str(q, ifcq3072, 10); + } else //Long term security + { + mpz_set_str(p, ifcp3072, 10); + mpz_set_str(g, ifcg3072, 10); + mpz_set_str(q, ifcq1024, 10); + } + + //TODO it would be better not to GMP's internal random generator, since it is not secure + gmp_randinit_default(rnd_state); + gmp_randseed(rnd_state, rnd_seed); + fe_bytelen = ceil_divide(secparam.ifcbits, 8); +} + +prime_field::~prime_field(){ + gmp_randclear(rnd_state); + mpz_clear(p); + mpz_clear(g); + mpz_clear(q); +} + + +gmp_brickexp::~gmp_brickexp() { + for(uint32_t i = 0; i < m_numberOfElements; i++) + mpz_clear(m_table[i]); + free(m_table); +}; + +void gmp_brickexp::init(fe* g, prime_field* pfield) { + field = pfield; + + m_numberOfElements = field->get_field_size(); + + m_table = (mpz_t*) malloc(sizeof(mpz_t) * m_numberOfElements); + for(uint32_t i = 0; i < m_numberOfElements; i++) + { + mpz_init(m_table[i]); + } + + mpz_set(m_table[0], *((gmp_fe*) g)->get_val()); + for (unsigned u=1; uget_p()); + } +} + +void gmp_brickexp::pow(fe* result, num* e) { + mpz_t* res = ((gmp_fe*) result)->get_val();//->set_ui(1);//(result, 1); + mpz_t* exp = ((gmp_num*) e)->get_val(); + uint32_t u; + + + mpz_set_ui(*res, 1); + for ( u=0; uget_p()); + } + } +} + + + + +// mpz_export does not fill leading zeros, thus a prepending of leading 0s is required +void mpz_export_padded(uint8_t* pBufIdx, uint32_t field_size_bytes, mpz_t to_export) { + size_t size = 0; + mpz_export(pBufIdx, &size, 1, sizeof(pBufIdx[0]), 0, 0, to_export); + + if (size < field_size_bytes) { + for (int i = 0; i + size < field_size_bytes; i++) { + pBufIdx[i] = 0; + } + pBufIdx += (field_size_bytes - size); + mpz_export(pBufIdx, &size, 1, sizeof(pBufIdx[0]), 0, 0, to_export); + } +} diff --git a/src/util/crypto/gmp-pk-crypto.h b/src/util/crypto/gmp-pk-crypto.h new file mode 100644 index 0000000..d2b7f13 --- /dev/null +++ b/src/util/crypto/gmp-pk-crypto.h @@ -0,0 +1,118 @@ +/* + * gmp_pk-crypto.h + * + * Created on: Jul 11, 2014 + * Author: mzohner + */ + +#ifndef GMP_PK_CRYPTO_H_ +#define GMP_PK_CRYPTO_H_ + +#include "pk-crypto.h" +#include + +class prime_field; +class gmp_fe; +class gmp_num; +class gmp_brickexp; + +#define fe2mpz(fieldele) (((gmp_fe*) (fieldele))->get_val()) +#define num2mpz(number) (((gmp_num*) (number))->get_val()) + +class prime_field : public pk_crypto { +public: + prime_field(seclvl sp, uint8_t* seed) : pk_crypto(sp, seed) {init(sp, seed);}; + ~prime_field(); + + num* get_num(); + num* get_rnd_num(uint32_t bitlen=0); + fe* get_fe(); + fe* get_rnd_fe(uint32_t bitlen); + fe* get_generator(); + fe* get_rnd_generator(); + + mpz_t* get_p(); + uint32_t get_size(); + //fe* sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen); + brickexp* get_brick(fe* gen); + + uint32_t num_byte_size() {return ceil_divide(secparam.ifcbits, 8);} + uint32_t get_field_size() {return secparam.ifcbits;}; + +protected: + void init(seclvl sp, uint8_t* seed); +private: + mpz_t p; + mpz_t g; + mpz_t q; + gmp_randstate_t rnd_state; +}; + + + +class gmp_fe : public fe { +public: + gmp_fe(prime_field* fld); + gmp_fe(prime_field* fld, mpz_t src); + ~gmp_fe(); + void set(fe* src); + mpz_t* get_val(); + + + void set_mul(fe* a, fe* b); + void set_pow(fe* b, num* e); + void set_div(fe* a, fe* b); + void set_double_pow_mul(fe* b1, num* e1, fe* b2, num* e2); + void export_to_bytes(uint8_t* buf); + void import_from_bytes(uint8_t* buf); + void sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen); + void print() {cout << val << endl;}; + +private: + void init() {mpz_init(val); }; + mpz_t val; + prime_field* field; + +}; + +class gmp_num : public num { +public: + gmp_num(prime_field* fld); + gmp_num(prime_field* fld, mpz_t src); + ~gmp_num(); + void set(num* src); + void set_si(int32_t src); + void set_add(num* a, num* b); + void set_mul(num* a, num* b); + + mpz_t* get_val(); + + void export_to_bytes(uint8_t* buf, uint32_t field_size); + void import_from_bytes(uint8_t* buf, uint32_t field_size); + void set_rnd(uint32_t bits); + void print() {cout << val << endl;}; +private: + mpz_t val; + prime_field* field; +}; + + +class gmp_brickexp : public brickexp { +public: + gmp_brickexp(fe* g, prime_field* pfield){init(g, pfield);}; + ~gmp_brickexp(); + + void pow(fe* result, num* e); + void init(fe* g, prime_field* pfield); + +private: + uint32_t m_numberOfElements; + mpz_t* m_table; + prime_field* field; +}; + + +// mpz_export does not fill leading zeros, thus a prepending of leading 0s is required +void mpz_export_padded(uint8_t* pBufIdx, uint32_t field_size, mpz_t to_export); + +#endif /* GMP_PK_CRYPTO_H_ */ diff --git a/src/util/crypto/pk-crypto.h b/src/util/crypto/pk-crypto.h new file mode 100644 index 0000000..aa9ce39 --- /dev/null +++ b/src/util/crypto/pk-crypto.h @@ -0,0 +1,88 @@ +/* + * pk-crypto.h + * + * Created on: Jul 10, 2014 + * Author: mzohner + */ + +#ifndef PK_CRYPTO_H_ +#define PK_CRYPTO_H_ + +#include "../typedefs.h" + + +class num; +class fe; +class brickexp; + +class pk_crypto { +public: + pk_crypto(seclvl sp, uint8_t* seed){}; + ~pk_crypto(){}; + virtual num* get_num() = 0; + virtual num* get_rnd_num(uint32_t bitlen=0) = 0; + virtual fe* get_fe() = 0; + virtual fe* get_rnd_fe(uint32_t bitlen) = 0; + virtual fe* get_generator() = 0; + virtual fe* get_rnd_generator() = 0; + virtual uint32_t num_byte_size() = 0; + //virtual fe* sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen) = 0; + uint32_t fe_byte_size() {return fe_bytelen;}; + virtual uint32_t get_field_size() =0; + virtual brickexp* get_brick(fe* gen) = 0; + + +protected: + virtual void init(seclvl secparam, uint8_t* seed) = 0; + uint32_t fe_bytelen; + seclvl secparam; +}; + + + + +//class number +class num { +public: + num(){}; + ~num(){}; + virtual void set(num* src) = 0; + virtual void set_si(int32_t src) = 0; + virtual void set_add(num* a, num* b) = 0; + virtual void set_mul(num* a, num* b) = 0; + virtual void export_to_bytes(uint8_t* buf, uint32_t field_size) = 0; + virtual void import_from_bytes(uint8_t* buf, uint32_t field_size) = 0; + virtual void print() = 0; +}; + + +//class field_element +class fe { +public: + fe(){}; + ~fe(){}; + virtual void set(fe* src) = 0; + virtual void set_mul(fe* a, fe* b) = 0; + virtual void set_pow(fe* b, num* e) = 0; + virtual void set_div(fe* a, fe* b) = 0; + virtual void set_double_pow_mul(fe* b1, num* e1, fe* b2, num* e2) = 0; + virtual void export_to_bytes(uint8_t* buf) = 0; + virtual void import_from_bytes(uint8_t* buf) = 0; + virtual void sample_fe_from_bytes(uint8_t* buf, uint32_t bytelen) = 0; + virtual void print() = 0; + +protected: + virtual void init() = 0; +}; + +class brickexp { +public: + brickexp(){}; + ~brickexp(){}; + + virtual void pow(fe* result, num* e) = 0; +}; + + + +#endif /* PK_CRYPTO_H_ */ diff --git a/src/util/miracl.a b/src/util/miracl.a new file mode 100644 index 0000000..c4508d3 Binary files /dev/null and b/src/util/miracl.a differ diff --git a/src/util/ot/baseOT.h b/src/util/ot/baseOT.h new file mode 100644 index 0000000..6d2020a --- /dev/null +++ b/src/util/ot/baseOT.h @@ -0,0 +1,53 @@ +/* + * baseOT.h + * + * Created on: Mar 20, 2013 + * Author: mzohner + */ + +#ifndef BASEOT_H_ +#define BASEOT_H_ + +#include "../typedefs.h" +#include "../cbitvector.h" +#include "../socket.h" +#include + +#include +#include +#include +#include +#include "../crypto/crypto.h" + +class BaseOT +{ + public: + BaseOT(crypto* crypt, field_type ftype){m_cCrypto = crypt; m_cPKCrypto = crypt->gen_field(ftype); }; + ~BaseOT(){delete m_cPKCrypto; }; + + virtual void Sender(uint32_t nSndVals, uint32_t nOTs, CSocket& sock, uint8_t* ret) = 0; + virtual void Receiver(uint32_t nSndVals, uint32_t uint32_t, CBitVector& choices, CSocket& sock, uint8_t* ret) = 0; + +protected: + + crypto* m_cCrypto; + pk_crypto* m_cPKCrypto; + //int m_nSecParam; + //fparams m_fParams; + //int m_nFEByteLen; + + //Big *m_BA, *m_BB, *m_BP; + //Big *m_X, *m_Y; + + //int m_nM, m_nA, m_nB, m_nC; + + void hashReturn(uint8_t* ret, uint32_t ret_len, uint8_t* val, uint32_t val_len, uint32_t ctr) { + m_cCrypto->hash_ctr(ret, ret_len, val, val_len, ctr); + } + + + + +}; + +#endif /* BASEOT_H_ */ diff --git a/src/util/ot/maskingfunction.h b/src/util/ot/maskingfunction.h new file mode 100644 index 0000000..66599fb --- /dev/null +++ b/src/util/ot/maskingfunction.h @@ -0,0 +1,33 @@ +/* + * MaskingFunction.h + * + * Created on: May 13, 2013 + * Author: mzohner + */ + +#ifndef MASKINGFUNCTION_H_ +#define MASKINGFUNCTION_H_ + +#include "../cbitvector.h" +#include "../typedefs.h" +#include "../crypto/crypto.h" + +class MaskingFunction +{ + +public: + MaskingFunction(){}; + ~MaskingFunction(){}; + + virtual void Mask(uint32_t progress, uint32_t len, CBitVector* values, CBitVector* snd_buf, uint8_t protocol) = 0; + virtual void UnMask(uint32_t progress, uint32_t len, CBitVector& choices, CBitVector& output, CBitVector& rcv_buf,CBitVector& tmpmask, uint8_t version) = 0; + virtual void expandMask(CBitVector& out, uint8_t* sbp, uint32_t offset, uint32_t processedOTs, uint32_t bitlength) = 0; + + +protected: + + +}; + + +#endif /* MASKINGFUNCTION_H_ */ diff --git a/src/util/ot/naor-pinkas.cpp b/src/util/ot/naor-pinkas.cpp new file mode 100644 index 0000000..c8a9431 --- /dev/null +++ b/src/util/ot/naor-pinkas.cpp @@ -0,0 +1,204 @@ +#include "naor-pinkas.h" + + + +void NaorPinkas::Receiver(uint32_t nSndVals, uint32_t nOTs, CBitVector& choices, + CSocket& socket, uint8_t* ret) { + + fe* PK0 = m_cPKCrypto->get_fe(); + fe** PK_sigma = (fe**) malloc(sizeof(fe*) * nOTs); + fe** pDec = (fe**) malloc(sizeof(fe*) * nOTs); + fe** pC = (fe**) malloc(sizeof(fe*) * nSndVals); + fe* g = m_cPKCrypto->get_generator(); + + num** pK = (num**) malloc(sizeof(num*) * nOTs); + + uint8_t* retPtr; + uint32_t u, k, choice, hash_bytes, fe_bytes; + hash_bytes = m_cCrypto->get_hash_bytes(); + fe_bytes = m_cPKCrypto->fe_byte_size(); + + + brickexp *bg, *bc; + bg = m_cPKCrypto->get_brick(g); //BrickInit(&bg, g, m_fParams); + + uint8_t* pBuf = (uint8_t*) malloc(sizeof(uint8_t) * nOTs * fe_bytes); + uint32_t nBufSize = nSndVals * fe_bytes; + + + //calculate the generator of the group + for (k = 0; k < nOTs; k++) + { + PK_sigma[k] = m_cPKCrypto->get_fe();// FieldElementInit(PK_sigma[k]); + pK[k] = m_cPKCrypto->get_rnd_num(); //FieldElementInit(pK[k]); + + //pK[k]->//GetRandomNumber(pK[k], m_fParams.secparam, m_fParams);/ + bg->pow(PK_sigma[k], pK[k]);//BrickPowerMod(&bg, PK_sigma[k], pK[k]); + } + + socket.Receive(pBuf, nBufSize); + uint8_t* pBufIdx = pBuf; + + for (u = 0; u < nSndVals; u++) { + pC[u] = m_cPKCrypto->get_fe();//FieldElementInit(pC[u]); + pC[u]->import_from_bytes(pBufIdx);//ByteToFieldElement(pC + u, m_fParams.elebytelen, pBufIdx); + pBufIdx += fe_bytes; + } + + bc = m_cPKCrypto->get_brick(pC[0]);//BrickInit(&bc, pC[0], m_fParams); + + //==================================================== + // N-P receiver: send pk0 + pBufIdx = pBuf; + for (k = 0; k < nOTs; k++) + { + choice = choices.GetBit((int32_t) k); + if (choice != 0) { + PK0->set_div(pC[choice], PK_sigma[k]);//FieldElementDiv(PK0, pC[choice], PK_sigma[k], m_fParams);//PK0 = pC[choice]; + } else { + PK0->set(PK_sigma[k]);//FieldElementSet(PK0, PK_sigma[k]);//PK0 = PK_sigma[k]; + } + //cout << "PK0: " << PK0 << ", PK_sigma: " << PK_sigma[k] << ", choice: " << choice << ", pC[choice: " << pC[choice] << endl; + PK0->export_to_bytes(pBufIdx);//FieldElementToByte(pBufIdx, m_fParams.elebytelen, PK0); + pBufIdx += fe_bytes;//m_fParams.elebytelen; + } + + socket.Send(pBuf, nOTs * m_cPKCrypto->fe_byte_size()); + + free(pBuf); + pBuf = (uint8_t*) malloc(sizeof(uint8_t) * fe_bytes);//new uint8_t[m_fParams.elebytelen]; + retPtr = ret; + + for (k = 0; k < nOTs; k++) { + pDec[k] = m_cPKCrypto->get_fe();//FieldElementInit(pDec[k]); + bc->pow(pDec[k], pK[k]);//BrickPowerMod(&bc, pDec[k], pK[k]); + pDec[k]->export_to_bytes(pBuf);//FieldElementToByte(pBuf, m_fParams.elebytelen, pDec[k]); + + hashReturn(retPtr, hash_bytes, pBuf, fe_bytes, k); + retPtr += hash_bytes;//SHA1_BYTES; + } + + delete bc;//BrickDelete(&bc); + delete bg;//BrickDelete(&bg); + + delete [] pBuf; + //TODO delete all field elements and numbers + free(PK_sigma); + free(pDec); + free(pC); + free(pK); +} + + + + +void NaorPinkas::Sender(uint32_t nSndVals, uint32_t nOTs, CSocket& socket, uint8_t* ret) +{ + num *alpha, *PKr, *tmp; + fe **pCr, **pC, *fetmp, *PK0r, *g, **pPK0; + uint8_t* pBuf, *pBufIdx; + uint32_t hash_bytes, fe_bytes, nBufSize, u, k; + + hash_bytes = m_cCrypto->get_hash_bytes(); + fe_bytes = m_cPKCrypto->fe_byte_size(); + + alpha = m_cPKCrypto->get_rnd_num(); + PKr = m_cPKCrypto->get_num(); + + pCr = (fe**) malloc(sizeof(fe*) * nSndVals); + pC = (fe**) malloc(sizeof(fe*) * nSndVals); + + fetmp = m_cPKCrypto->get_fe(); + PK0r = m_cPKCrypto->get_fe(); + pC[0] = m_cPKCrypto->get_fe(); + g = m_cPKCrypto->get_generator(); + + + + /*FieldElementInit(alpha); + FieldElementInit(fetmp); + FieldElementInit(pC[0]); + FieldElementInit(PK0r); + FieldElementInit(tmp);*/ + + //random C1 + //GetRandomNumber(alpha, m_fParams.secparam, m_fParams);//alpha = rand(m_nSecParam, 2);//TODO + pC[0]->set_pow(g, alpha);//FieldElementPow(pC[0], g, alpha, m_fParams); + + //random C(i+1) + for (u = 1; u < nSndVals; u++) { + pC[u] = m_cPKCrypto->get_fe();//FieldElementInit(pC[u]); + tmp = m_cPKCrypto->get_rnd_num(); + //GetRandomNumber(tmp, m_fParams.secparam, m_fParams);//alpha = rand(m_nSecParam, 2); //TODO + pC[u]->set_pow(g, tmp);//FieldElementPow(pC[u], g, tmp, m_fParams); + } + + //==================================================== + // Export the generated C_1-C_nSndVals to a uint8_t vector and send them to the receiver + nBufSize = nSndVals * fe_bytes; + pBuf = (uint8_t*) malloc(nBufSize); + pBufIdx = pBuf; + for (u = 0; u < nSndVals; u++) { + pC[u]->export_to_bytes(pBufIdx);//FieldElementToByte(pBufIdx, m_fParams.elebytelen, pC[u]); + pBufIdx += fe_bytes;//m_fParams.elebytelen; + } + socket.Send(pBuf, nBufSize); + + //==================================================== + // compute C^R + for (u = 1; u < nSndVals; u++) { + pCr[u] = m_cPKCrypto->get_fe();//FieldElementInit(pCr[u]); + pCr[u]->set_pow(pC[u], alpha);//FieldElementPow(pCr[u], pC[u], alpha, m_fParams); + } + //==================================================== + + free(pBuf); + // N-P sender: receive pk0 + nBufSize = fe_bytes * nOTs; + pBuf = (uint8_t*) malloc(nBufSize); + socket.Receive(pBuf, nBufSize); + + pBufIdx = pBuf; + + pPK0 = (fe**) malloc(sizeof(fe*) * nOTs); + for (k = 0; k < nOTs; k++) { + pPK0[k] = m_cPKCrypto->get_fe(); + //FieldElementInit(pPK0[k]); + pPK0[k]->import_from_bytes(pBufIdx); + //ByteToFieldElement(pPK0 + k, m_fParams.elebytelen, pBufIdx); + pBufIdx += fe_bytes; + } + + //==================================================== + // Write all nOTs * nSndVals possible values to ret + //free(pBuf); TODO fix and uncomment + pBuf = (uint8_t*) malloc(sizeof(uint8_t) * fe_bytes * nSndVals); + uint8_t* retPtr = ret; + fetmp = m_cPKCrypto->get_fe(); + + for (k = 0; k < nOTs; k++) + { + pBufIdx = pBuf; + for (u = 0; u < nSndVals; u++) { + + if (u == 0) { + // pk0^r + PK0r->set_pow(pPK0[k], alpha);//FieldElementPow(PK0r, pPK0[k], alpha, m_fParams); + PK0r->export_to_bytes(pBufIdx);//FieldElementToByte(pBufIdx, m_fParams.elebytelen, PK0r); + + } else { + // pk^r + fetmp->set_div(pCr[u], PK0r);//FieldElementDiv(fetmp, pCr[u], PK0r, m_fParams); + fetmp->export_to_bytes(pBufIdx);//FieldElementToByte(pBufIdx, m_fParams.elebytelen, fetmp); + } + hashReturn(retPtr, hash_bytes, pBufIdx, fe_bytes, k); + pBufIdx += fe_bytes; + retPtr += hash_bytes; + } + + } + + //free(pBuf); + free(pCr); + free(pC); +} diff --git a/src/util/ot/naor-pinkas.h b/src/util/ot/naor-pinkas.h new file mode 100644 index 0000000..ce960a8 --- /dev/null +++ b/src/util/ot/naor-pinkas.h @@ -0,0 +1,26 @@ +/* + * Compute the Naor-Pinkas Base OTs + */ + +#ifndef __Naor_Pinkas_H_ +#define __Naor_Pinkas_H_ + +#include "baseOT.h" + +class NaorPinkas : public BaseOT +{ + + public: + + NaorPinkas(crypto* crypto, field_type ftype) : BaseOT(crypto, ftype) {}; + ~NaorPinkas(){}; + + void Receiver(uint32_t nSndVals, uint32_t nOTs, CBitVector& choices, CSocket& sock, uint8_t* ret); + void Sender(uint32_t nSndVals, uint32_t nOTs, CSocket& sock, uint8_t* ret); + + +}; + + + +#endif diff --git a/src/util/ot/opemasking.h b/src/util/ot/opemasking.h new file mode 100644 index 0000000..51d148f --- /dev/null +++ b/src/util/ot/opemasking.h @@ -0,0 +1,236 @@ +/* + * XORMasking.h + * + * Created on: May 13, 2013 + * Author: mzohner + */ + +#ifndef OPEMASKING_H_ +#define OPEMASKING_H_ + +#include "maskingfunction.h" + +//#define DEBUG_HASH_INPUT +//#define DEBUG_HASH_OUTPUT +//#define FIXED_KEY_AES_HASH_OPRG + +#ifdef FIXED_KEY_AES_HASH_OPRG +static const uint8_t fixedkeyseed[AES_BYTES] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; +#endif + +class OPEMasking : public MaskingFunction +{ +public: + //Constructor that is called by the server + OPEMasking(uint32_t itembitlen, uint32_t maskbitlen, uint32_t nbins, uint32_t* nelements, CBitVector& server_choices, CBitVector& results, crypto* crypt) { + m_vServerChoices = server_choices; + m_vNumEleInBin = nelements; + init(itembitlen, maskbitlen, results, crypt, true); + InitAndReadCodeWord(&m_vCodeWords); + m_vStartingPosForBin = (uint32_t*) malloc(sizeof(uint32_t) * nbins); + assert(nbins > 0); + m_vStartingPosForBin[0] = 0; + m_nExpansionFactor = 1; + for(uint32_t i = 1; i < nbins; i++) { + m_vStartingPosForBin[i] = m_vStartingPosForBin[i-1] + m_vNumEleInBin[i-1]; + if(m_vNumEleInBin[i] > m_nCodeWordBits) { + m_nExpansionFactor = m_nCodeWordBits; + } + } + if(m_vNumEleInBin[0] > m_nCodeWordBits) { + m_nExpansionFactor = m_nCodeWordBits; + } + }; + + //Constructor that is called by the client + OPEMasking(uint32_t itembitlen, uint32_t maskbitlen, uint32_t nbins, uint32_t* nelements, CBitVector& results, crypto* crypt) + { + init(itembitlen, maskbitlen, results, crypt, false); + + m_vNumEleInBin = nelements; + m_vBinToResult = (uint32_t*) calloc(nbins, sizeof(uint32_t)); + + for(uint32_t i = 1; i < nbins; i++) { + m_vBinToResult[i] = m_vBinToResult[i-1] + m_vNumEleInBin[i-1]; + } + }; + + ~OPEMasking(){ + //TODO id whether client or server routine is used + }; + + void init(uint32_t itembitlen, uint32_t maskbitlen, CBitVector& results, crypto* crypt, bool server) + { + m_nItemBitLen = itembitlen; + m_nMaskBitLen = maskbitlen; + m_vResults = results; + m_cCrypto = crypt; + m_bServer = server; + m_nOTsPerElement = ceil_divide(m_nItemBitLen, 8); +#ifdef FIXED_KEY_AES_HASH_OPRG + m_kCRFKey = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX)); + m_cCrypto->init_aes_key(m_kCRFKey, (uint8_t*) fixedkeyseed, ECB); + //MPC_AES_KEY_INIT(m_kCRFKey); + //MPC_AES_KEY_EXPAND(m_kCRFKey, fixedkeyseed); +#endif + } + + //Expansion routine for the server + void ServerExpand(CBitVector& matrix, uint8_t* uptr, uint32_t ot_begin_id, uint32_t processedOTs) { + uint64_t ot_id, bin_id, bit_id, u, binoffset; + uint8_t *Mptr = matrix.GetArr(); + CBitVector mask(m_nCodeWordBits * m_nExpansionFactor); + uint8_t* hash_buf = (uint8_t*) malloc(m_nCodeWordBytes * m_nExpansionFactor); + uint8_t* mask_ptr = mask.GetArr(); + uint8_t* hash_ptr; + + //m_vServerChoices.PrintHex(); + for(ot_id = ot_begin_id; ot_id < ot_begin_id+processedOTs; ot_id++, Mptr+=m_nCodeWordBytes) + { + bin_id = ot_id/m_nOTsPerElement; + bit_id = ot_id%m_nOTsPerElement; + + binoffset = m_vStartingPosForBin[bin_id] * m_nOTsPerElement; + + if(m_vNumEleInBin[bin_id] < m_nCodeWordBits) { + //cout << "Choice for ot_id = " << ot_id << ": "; + for(u = 0; u < m_vNumEleInBin[bin_id]; u++) + { + //cout << "Server expanding for bin_id : " << bin_id << " and element id " << u << endl; + mask.Copy(uptr, 0, m_nCodeWordBytes); + //mask.ANDBytes((uint8_t*) m_vCodeWords[m_vServerChoices[bin_id].Get((bit_id + u* m_nOTsPerElement) * 8, 8)], 0, m_nCodeWordBytes); + mask.ANDBytes((uint8_t*) m_vCodeWords[m_vServerChoices.Get((binoffset + bit_id + u* m_nOTsPerElement) * 8, 8)], 0, m_nCodeWordBytes); + //cout << (hex) << m_vServerChoices[bin_id].Get((bit_id + u* m_nOTsPerElement) * 8, 8) << (dec) << " "; + mask.XORBytes(Mptr, m_nCodeWordBytes); + #ifdef DEBUG_HASH_INPUT + cout << "hash input for ot_id = " << ot_id <<" and choice = " << (hex) << + m_vServerChoices.Get((binoffset + bit_id + u* m_nOTsPerElement) * 8, 8) << (dec) <<": "; + mask.PrintHex(); + #endif + #ifdef FIXED_KEY_AES_HASH_OPRG + ((uint64_t*) mask_ptr)[0] ^= ot_id; + m_cCrypto->aes_compression_hash(m_kCRFKey, hash_buf, mask_ptr, m_nCodeWordBytes); + #else + m_cCrypto->hash_ctr(hash_buf, AES_BYTES, mask_ptr, m_nCodeWordBytes, ot_id); + #endif + // cout << "MaskBitLen: " << m_nMaskBitLen << ", results size = " << m_vResults[bin_id].GetSize() << endl; + //cout << "(" << (hex) << ((uint64_t*) hash_buf)[0] << ") " << (dec); + #ifdef DEBUG_HASH_OUTPUT + cout << "hash output for ot_id = " << ot_id << " and element_id = " << u << ": "; + for(uint32_t j = 0; j < AES_BYTES; j++) + cout << (hex) << (unsigned int) hash_buf[j]; + cout << (dec) << endl; + #endif + //TODO: permute the values at this point - write into a permuted index + m_vResults.XORBits(hash_buf, ((uint64_t) m_vStartingPosForBin[bin_id] + u) * m_nMaskBitLen, (uint64_t) m_nMaskBitLen); + //m_vResults[bin_id].PrintHex(); + } + } else { + for(u = 0; u < m_nCodeWordBits; u++) { + mask.Copy(uptr, u*m_nCodeWordBytes, m_nCodeWordBytes); + mask.ANDBytes((uint8_t*) m_vCodeWords[u], u*m_nCodeWordBytes, m_nCodeWordBytes); + mask.XORBytes(Mptr, (uint64_t) u*m_nCodeWordBytes, (uint64_t) m_nCodeWordBytes); + } + + for(u = 0, hash_ptr=hash_buf, mask_ptr=mask.GetArr(); u < m_nCodeWordBits; u++, mask_ptr+=m_nCodeWordBytes, hash_ptr+=AES_BYTES) { +#ifdef FIXED_KEY_AES_HASH_OPRG + ((uint32_t*) mask_ptr)[0] ^= ot_id; + m_cCrypto->aes_compression_hash(m_kCRFKey, hash_ptr, mask_ptr, m_nCodeWordBytes); +#else + m_cCrypto->hash_ctr(hash_buf, AES_BYTES, mask_ptr, m_nCodeWordBytes, ot_id); +#endif + } + uint64_t mask_id; + for(u = 0; u < m_vNumEleInBin[bin_id]; u++) { + mask_id = m_vServerChoices.Get((binoffset + bit_id + u* m_nOTsPerElement) * 8, 8); + m_vResults.XORBits(hash_buf+mask_id*AES_BYTES, ((uint64_t) m_vStartingPosForBin[bin_id] + u) * m_nMaskBitLen, (uint64_t) m_nMaskBitLen); + } + } + + //cout << endl; + } + mask.delCBitVector(); + free(hash_buf); + } + + //Expansion routine for the client + void ClientExpand(CBitVector& matrix, uint32_t ot_begin_id, uint32_t processedOTs) { + //uint8_t hash_buf[m_cCrypto->get_hash_bytes()]; + uint64_t ot_id, bin_id; + uint8_t *Mptr = matrix.GetArr(); + uint8_t* hash_buf = (uint8_t*) malloc(m_nCodeWordBytes); + + for(ot_id = ot_begin_id; ot_id < ot_begin_id+processedOTs; ot_id++, Mptr+=m_nCodeWordBytes) + { + + bin_id = ot_id/m_nOTsPerElement; + if(m_vNumEleInBin[bin_id] > 0) { +#ifdef DEBUG_HASH_INPUT + cout << "hash input for ot_id = " << ot_id << ": "; + for(uint32_t j = 0; j < m_nCodeWordBytes; j++) + cout << (hex) << (unsigned int) Mptr[j]; + cout << endl; +#endif + +#ifdef FIXED_KEY_AES_HASH_OPRG + ((uint64_t*) Mptr)[0] ^= ot_id; + m_cCrypto->aes_compression_hash(m_kCRFKey, hash_buf, Mptr, m_nCodeWordBytes); +#else + m_cCrypto->hash_ctr(hash_buf, AES_BYTES, Mptr, m_nCodeWordBytes, ot_id); +#endif + + // cout << "Client expanding for bin_id : " << bin_id << endl; + // cout << "MaskBitLen: " << m_nMaskBitLen << endl; + m_vResults.XORBits(hash_buf, ((uint64_t) m_vBinToResult[bin_id]) * m_nMaskBitLen, (uint64_t) m_nMaskBitLen); + //m_vResults[bin_id].PrintHex(); + //cout << "otid = " << ot_id << ": " << (hex) << ((uint64_t*) hash_buf)[0] << (dec) << endl; +#ifdef DEBUG_HASH_OUTPUT + cout << "hash output for ot_id = " << ot_id << ": "; + for(uint32_t j = 0; j < AES_BYTES; j++) + cout << (hex) << (unsigned int) hash_buf[j]; + cout << (dec) << endl; +#endif + } + } + free(hash_buf); + } + + //the out vector contains the matrix with the data that needs to be hashed, uptr is a pointer to the choice-bits of the server in the base-OTs + void expandMask(CBitVector& matrix, uint8_t* uptr, uint32_t ot_begin_id, uint32_t processedOTs, uint32_t bitlength) { + if(m_bServer) { + ServerExpand(matrix, uptr, ot_begin_id, processedOTs); + } else { + ClientExpand(matrix, ot_begin_id, processedOTs); + } + } + + //Do nothing, only dummy function to implement virtual function + void Mask(uint32_t progress, uint32_t processedOTs, CBitVector* values, CBitVector* snd_buf, + uint8_t protocol) {}; + + + //TODO: update, not working any more since unmask was changed + void UnMask(uint32_t progress, uint32_t processedOTs, CBitVector& choices, CBitVector& output, + CBitVector& rcv_buf, CBitVector& tempmasks, uint8_t protocol) { }; + +private: + uint32_t m_nItemBitLen; + uint32_t m_nMaskBitLen; + uint32_t m_nOTsPerElement; + uint8_t m_bBuf[AES_BYTES]; + uint8_t ctr_buf[AES_BYTES]; + uint32_t* m_vBinToResult; + uint32_t* m_vNumEleInBin; + uint32_t* m_vStartingPosForBin; + CBitVector m_vServerChoices; + CBitVector m_vResults; + crypto* m_cCrypto; + uint32_t m_nExpansionFactor; + bool m_bServer; + REGISTER_SIZE** m_vCodeWords; +#ifdef FIXED_KEY_AES_HASH_OPRG + AES_KEY_CTX* m_kCRFKey; +#endif +}; + +#endif /* OPEMASKING_H */ diff --git a/src/util/ot/ot-extension-1oon-ecc.cpp b/src/util/ot/ot-extension-1oon-ecc.cpp new file mode 100644 index 0000000..47ea3ff --- /dev/null +++ b/src/util/ot/ot-extension-1oon-ecc.cpp @@ -0,0 +1,624 @@ +#include "ot-extension-1oon-ecc.h" + +bool OTExtension1ooNECCReceiver::receive(uint32_t numOTs, uint32_t bitlength, CBitVector& choices, CBitVector& ret, uint8_t type, uint32_t numThreads, MaskingFunction* unmaskfct) { + m_nOTs = numOTs; + m_nBitLength = bitlength; + m_nChoices = choices; + m_nRet = ret; + m_bProtocol = type; + m_fMaskFct = unmaskfct; + return receive(numThreads); +}; + +//Initialize and start numThreads OTSenderThread +bool OTExtension1ooNECCReceiver::receive(uint32_t numThreads) +{ + if(m_nOTs == 0) + return true; + + if(m_bProtocol != R_OT && m_bProtocol != RN_OT) { + cerr << "Only working with R_OT or RN_OT right now, sorry!" << endl; + return false; + } + + //The total number of OTs that is performed has to be a multiple of numThreads*Z_REGISTER_BITS + uint32_t internal_numOTs = ceil_divide(pad_to_multiple(m_nOTs, REGISTER_BITS), numThreads); + //cout << "Internal num OTs: " << internal_numOTs << endl; + //uint8_t go; + //Wait for the signal of the corresponding sender thread + //sock.Receive(&go, 1); + + vector rThreads(numThreads); + for(uint32_t i = 0; i < numThreads; i++) + { + rThreads[i] = new OTReceiverThread(i, internal_numOTs, this); + rThreads[i]->Start(); + } + + for(uint32_t i = 0; i < numThreads; i++) + { + rThreads[i]->Wait(); + } + m_nCounter += m_nOTs; + + for(uint32_t i = 0; i < numThreads; i++) + delete rThreads[i]; + +#ifdef VERIFY_OT + //Wait for the signal of the corresponding sender thread + uint8_t finished = 0x01; + m_nSockets[0].Send(&finished, 1); + + verifyOT(m_nOTs); +#endif + + return true; +} + + + +bool OTExtension1ooNECCReceiver::OTReceiverRoutine(uint32_t id, uint32_t myNumOTs) +{ + //cout << "Thread " << id << " started" << endl; + uint32_t myStartPos = id * myNumOTs; + uint32_t i = myStartPos; + + myNumOTs = min(myNumOTs + myStartPos, m_nOTs) - myStartPos; + uint32_t lim = myStartPos+myNumOTs; + + //How many batches of OTEXT_BLOCK_SIZE_BITS OTs should be performed? + uint32_t processedOTBlocks = min((uint32_t) NUMOTBLOCKS, ceil_divide(myNumOTs, m_nCodeWordBits)); + //How many OTs should be performed per iteration + uint32_t OTsPerIteration = processedOTBlocks * m_nCodeWordBits; + uint32_t OTwindow = NUMOTBLOCKS*m_nCodeWordBits; + CSocket* sock = m_nSockets+id; + + //counter variables + uint32_t nSize; + + // A temporary part of the T matrix + CBitVector T(m_nCodeWordBits * OTsPerIteration); + T.Reset(); + // The send buffer + CBitVector vSnd(m_nCodeWordBits * OTsPerIteration); + // Stores the codes for the choice bits + CBitVector choicecodes(m_nCodeWordBits * m_nCodeWordBits); + choicecodes.Reset(); + // A temporary buffer that stores the resulting seeds from the hash buffer + CBitVector seedbuf(OTwindow*AES_BITS);// = new CBitVector[RoundWindow]; + + uint8_t ctr_buf[AES_BYTES] = {0}; + uint32_t* counter = (uint32_t*) ctr_buf; + (*counter) = myStartPos + m_nCounter; + +#ifdef TIMING + double totalMtxTime = 0, totalTnsTime = 0, totalHshTime = 0, totalRcvTime = 0, totalSndTime = 0, totalChcTime = 0; + timeval tempStart, tempEnd; +#endif + + while( i < lim ) + { + processedOTBlocks = min((uint32_t) NUMOTBLOCKS, ceil_divide(lim-i, m_nCodeWordBits)); + OTsPerIteration = processedOTBlocks * m_nCodeWordBits; + +#ifdef TIMING + gettimeofday(&tempStart, NULL); +#endif +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalChcTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + BuildMatrices(T, vSnd, processedOTBlocks, i, ctr_buf); + GenerateChoiceCodes(choicecodes, vSnd, i, min(lim-i, OTsPerIteration)); + +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalMtxTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + T.EklundhBitTranspose(m_nCodeWordBits, OTsPerIteration); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalTnsTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + //cout << "offset: " << (AES_KEY_uint8_tS * (i-nProgress))<< ", i = " << i << ", nprogress = " << nProgress << ", otwindow = " << OTwindow << endl; + HashValues(T, seedbuf, i, min(lim-i, OTsPerIteration)); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalHshTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + + nSize = m_nCodeWordBytes * OTsPerIteration; + //cout << "Sending " << nSize << " Bytes " << endl; + //m_lRcvLock->Lock(); + //cout << "(" << id << ") Sending " << nSize << " bytes on OT " << i << endl; + sock->Send( vSnd.GetArr(), nSize ); + //cout << "(" << id << ") sent " << nSize << " bytes for OT " << i << endl; + //vSnd.PrintHex(0,1024); + //m_lRcvLock->Unlock(); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalSndTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + i+=min(lim-i, OTsPerIteration); + //cout << "Performing next OTs " << i << ", OTsPerItation = " << OTsPerIteration << endl; + +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalRcvTime += getMillies(tempStart, tempEnd); +#endif + vSnd.Reset(); + } + + T.delCBitVector(); + vSnd.delCBitVector(); + seedbuf.delCBitVector(); + choicecodes.delCBitVector(); + +#ifdef TIMING + cout << "Receiver time benchmark for performing " << myNumOTs << " OTs on " << m_nBitLength << " bit strings" << endl; + cout << "Time needed for: " << endl; + cout << "\t Generating Choice-Code:t" << totalChcTime << " ms" << endl; + cout << "\t Matrix Generation:\t" << totalMtxTime << " ms" << endl; + cout << "\t Sending Matrix:\t" << totalSndTime << " ms" << endl; + cout << "\t Transposing Matrix:\t" << totalTnsTime << " ms" << endl; + cout << "\t Hashing Matrix:\t" << totalHshTime << " ms" << endl; + cout << "\t Receiving Values:\t" << totalRcvTime << " ms" << endl; +#endif + + //sleep(1); + return TRUE; +} + +void OTExtension1ooNECCReceiver::GenerateChoiceCodes(CBitVector& choicecodes, CBitVector& vSnd, uint32_t startpos, uint32_t len) { + uint32_t tmpchoice; + uint32_t otid = startpos; + uint32_t ncolumnsbyte = ceil_divide(len, m_nCodeWordBits) * m_nCodeWordBytes; + for(uint32_t pos = 0; pos < len; pos+=m_nCodeWordBits) { + choicecodes.Reset(); + for(uint32_t j = 0; j < min(len - pos, m_nCodeWordBits); j++, otid++) { + tmpchoice = m_nChoices.Get(otid * 8, 8); + //cout << "otid = " << otid << ", choice = " << tmpchoice << endl; +#ifdef ZDEBUG + cout << "my choice : " << tmpchoice << endl; +#endif + choicecodes.SetBytes((uint8_t*) m_vCodeWords[tmpchoice], j*m_nCodeWordBytes, m_nCodeWordBytes); + } + choicecodes.EklundhBitTranspose(m_nCodeWordBits, m_nCodeWordBits); + for(uint32_t j = 0; j < m_nCodeWordBits; j++) { + vSnd.XORBytes(choicecodes.GetArr() + j * m_nCodeWordBytes, (pos >> 3) + j * ncolumnsbyte, m_nCodeWordBytes); + // cout << "accessing byte: " << (pos >> 3) + j * ncolumnsbyte << endl; + /*cout << "S: "; + for(uint32_t i = 0; i < m_nCodeWordBytes; i++) { + cout << (hex) << (unsigned int) *(vSnd.GetArr() + j * m_nCodeWordBytes + i); + } + cout << (dec) << endl;*/ + } + } +} + + + +void OTExtension1ooNECCReceiver::BuildMatrices(CBitVector& T, CBitVector& SndBuf, uint32_t numblocks, uint32_t ctr, uint8_t* ctr_buf) +{ + uint32_t* counter = (uint32_t*) ctr_buf; + uint32_t tempctr = (*counter); + + uint8_t* Tptr = T.GetArr(); + uint8_t* sndbufptr = SndBuf.GetArr(); + + //cout << "Numblocks = " << numblocks << endl; + for(uint32_t k = 0; k < m_nCodeWordBits; k++) + { + (*counter) = tempctr; + for(uint32_t b = 0; b < 2*numblocks; b++, (*counter)++) + { + m_cCrypto->encrypt(m_vKeySeedMtx + 2*k, Tptr, ctr_buf, AES_BYTES);//MPC_AES_ENCRYPT(m_vKeySeedMtx + 2*k, Tptr, ctr_buf); + Tptr+=OTEXT_BLOCK_SIZE_BYTES; + + m_cCrypto->encrypt(m_vKeySeedMtx + 2*k + 1, sndbufptr, ctr_buf, AES_BYTES);//MPC_AES_ENCRYPT(m_vKeySeedMtx + (2*k) + 1, sndbufptr, ctr_buf); + sndbufptr+=OTEXT_BLOCK_SIZE_BYTES; + } + +#ifdef DEBUG_PRG_OUTPUT + cout << "I: "; + for(uint32_t i = 0; i < AES_BYTES; i++) { + cout << (hex) << (unsigned int) *(ctr_buf + i); + } + cout << endl << "T: "; + for(uint32_t i = 0; i < OTEXT_BLOCK_SIZE_BYTES*2; i++) { + cout << (hex) << (unsigned int) *(Tptr-(2*OTEXT_BLOCK_SIZE_BYTES) + i); + } + cout << endl << "S: "; + for(uint32_t i = 0; i < OTEXT_BLOCK_SIZE_BYTES*2; i++) { + cout << (hex) << (unsigned int) *(sndbufptr-(2*OTEXT_BLOCK_SIZE_BYTES) + i); + } + cout << endl; +#endif + } + SndBuf.XORBytes(T.GetArr(), (uint32_t) 0, m_nCodeWordBytes*numblocks*m_nCodeWordBits); +} + + +void OTExtension1ooNECCReceiver::HashValues(CBitVector& T, CBitVector& seedbuf, uint32_t ctr, uint32_t processedOTs) +{ + //If OT-based PSI is performed, the hashing is skipped and the masking is called directly + if(m_bProtocol == RN_OT) { + m_fMaskFct->expandMask(T, seedbuf.GetArr(), ctr, processedOTs, m_nBitLength); //m_sSecParam.statbits + return; + } + + uint8_t* Tptr = T.GetArr(); + uint8_t* bufptr = seedbuf.GetArr();//m_vSeedbuf.GetArr() + ctr * AES_KEY_uint8_tS;//seedbuf.GetArr(); + + //HASH_CTX sha; + uint8_t hash_buf[m_cCrypto->get_hash_bytes()]; + + for(uint32_t i = ctr; i < ctr+processedOTs; i++, Tptr+=m_nCodeWordBytes, bufptr+=AES_BYTES) + { +#ifdef DEBUG_HASH_INPUT + cout << "hash input for i = " << i << " and choice = " << (uint32_t) m_nChoices.Get(i) << ": "; + T.PrintHex((i-ctr) * m_nCodeWordBytes, (i-ctr+1) * m_nCodeWordBytes); +#endif + m_cCrypto->hash_ctr(bufptr, AES_BYTES, Tptr, m_nCodeWordBytes, i); + //MPC_HASH_INIT(&sha); + //MPC_HASH_UPDATE(&sha, (uint8_t*) &i, sizeof(i)); + //MPC_HASH_UPDATE(&sha, Tptr, m_nCodeWordBytes); + //MPC_HASH_FINAL(&sha, hash_buf); + //memcpy(bufptr, hash_buf, AES_BYTES); +#ifdef DEBUG_HASH_OUTPUT + cout << "hash output for i = " << i << " and choice = " << (uint32_t) m_nChoices.Get(i) << ": "; + for(uint32_t j = 0; j < AES_BYTES; j++) + cout << (hex) << (unsigned int) bufptr[j]; + cout << (dec) << endl; +#endif + } + + m_fMaskFct->expandMask(m_nRet, seedbuf.GetArr(), ctr, processedOTs, m_nBitLength); + + +} + + +bool OTExtension1ooNECCReceiver::verifyOT(uint32_t NumOTs) +{ + CSocket sock = m_nSockets[0]; + CBitVector vRcvX[m_nSndVals]; + for(uint32_t u = 0; u < m_nSndVals; u++) { + vRcvX[u].Create(NUMOTBLOCKS*m_nCodeWordBits*m_nBitLength); + } + CBitVector* Xc; + uint64_t processedOTBlocks, OTsPerIteration; + uint64_t bytelen = ceil_divide(m_nBitLength, 8); + uint8_t* tempXc = new uint8_t[bytelen]; + uint8_t* tempRet = new uint8_t[bytelen]; + uint8_t resp; + for(uint64_t i = 0; i < NumOTs;) { + processedOTBlocks = min((uint64_t) NUMOTBLOCKS, ceil_divide(NumOTs-i, m_nCodeWordBits)); + //OTsPerIteration = processedOTBlocks * Z_REGISTER_BITS; + OTsPerIteration = min(processedOTBlocks * m_nCodeWordBits, NumOTs-i); + for(uint32_t u = 0; u < m_nSndVals; u++) { + sock.Receive(vRcvX[u].GetArr(), ceil_divide(m_nBitLength * OTsPerIteration, 8)); + } + for(uint32_t j = 0; j < OTsPerIteration && i < NumOTs; j++, i++) + { + Xc = &(vRcvX[m_nChoices.Get(i)]); + + Xc->GetBits(tempXc, j*m_nBitLength, m_nBitLength); + m_nRet.GetBits(tempRet, i*m_nBitLength, m_nBitLength); + for(uint32_t k = 0; k < bytelen; k++) + { + if(tempXc[k] != tempRet[k]) + { + cout << "Error at position i = " << i << ", k = " << k << ", with X" << (hex) << (uint32_t) m_nChoices.GetBitNoMask((uint64_t) i) + << " = " << (uint32_t) tempXc[k] << " and res = " << (uint32_t) tempRet[k] << (dec) << endl; + //<< " = " << ((uint32_t*) (tempXc + k))[0] << " and res = " << ((uint32_t*) (tempRet + k))[0] << (dec) << endl; + resp = 0x00; + sock.Send(&resp, 1); + return false; + } + } + } + resp = 0x01; + sock.Send(&resp, 1); + } + delete[] tempXc; + delete[] tempRet; + + for(uint32_t u = 0; u < m_nSndVals; u++) + vRcvX[u].delCBitVector(); + cout << "OT Verification successful" << endl; + return true; +} + + + +bool OTExtension1ooNECCSender::send(uint32_t numOTs, uint32_t bitlength, CBitVector* values, uint8_t type, + uint32_t numThreads, MaskingFunction* maskfct) +{ + m_nOTs = numOTs; + m_nBitLength = bitlength; + m_vValues = values; + m_bProtocol = type; + m_fMaskFct = maskfct; + return send(numThreads); +} + + +//Initialize and start numThreads OTSenderThread +bool OTExtension1ooNECCSender::send(uint32_t numThreads) +{ + if(m_nOTs == 0) + return true; + + if(m_bProtocol != R_OT && m_bProtocol != RN_OT) { + cerr << "Only working with R_OT or RN_OT right now, sorry!" << endl; + return false; + } + + + //The total number of OTs that is performed has to be a multiple of numThreads*Z_REGISTER_BITS + uint32_t numOTs = ceil_divide(pad_to_multiple(((uint64_t) m_nOTs), REGISTER_BITS), numThreads); + //cout << "numOTs: " << numOTs << endl; + m_nBlocks = 0; + m_lSendLock = new CLock; + + vector sThreads(numThreads); + + //uint8_t go; + //sock.Send(&go, 1); + + + for(uint32_t i = 0; i < numThreads; i++) + { + sThreads[i] = new OTSenderThread(i, numOTs, this); + sThreads[i]->Start(); + } + + for(uint32_t i = 0; i < numThreads; i++) + { + sThreads[i]->Wait(); + } + m_nCounter += m_nOTs; + + for(uint32_t i = 0; i < numThreads; i++) + delete sThreads[i]; + +#ifdef VERIFY_OT + uint8_t finished; + m_nSockets[0].Receive(&finished, 1); + + verifyOT(m_nOTs); +#endif + + + return true; +} + + +//bool OTsender(uint32_t nSndVals, uint32_t nOTs, uint32_t startpos, CSocket& sock, CBitVector& U, AES_KEY* vKeySeeds, CBitVector* values, uint8_t* seed) +bool OTExtension1ooNECCSender::OTSenderRoutine(uint32_t id, uint32_t myNumOTs) +{ + CSocket* sock = m_nSockets + id; + + uint32_t nProgress; + uint32_t myStartPos = id * myNumOTs; + uint32_t processedOTBlocks = min((uint32_t) NUMOTBLOCKS, ceil_divide(myNumOTs, m_nCodeWordBits)); + uint32_t OTsPerIteration = processedOTBlocks * m_nCodeWordBits; + + myNumOTs = min(myNumOTs + myStartPos, m_nOTs) - myStartPos; + uint32_t lim = myStartPos+myNumOTs; + + // The vector with the received bits + CBitVector vRcv(m_nCodeWordBits * OTsPerIteration); + + CBitVector* seedbuf = new CBitVector[m_nSndVals]; + for(uint32_t u = 0; u < m_nSndVals; u++) + seedbuf[u].Create(OTsPerIteration* AES_BITS); +#ifdef ZDEBUG + cout << "seedbuf size = " <Lock(); + //cout << "(" << id << ") Waiting for " << OTsPerIteration * m_nCodeWordBytes << " bytes on OT " << nProgress << endl; + sock->Receive(vRcv.GetArr(), OTsPerIteration * m_nCodeWordBytes); + //cout << "(" << id << ") received " << OTsPerIteration * m_nCodeWordBytes << " bytes for OT " << nProgress << endl; + //vRcv.PrintHex(0,1024); + //m_lSendLock->Unlock(); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalRcvTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + BuildQMatrix(Q, vRcv, processedOTBlocks, ctr_buf); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalMtxTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + Q.EklundhBitTranspose(m_nCodeWordBits, OTsPerIteration); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalTnsTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + MaskInputs(Q, seedbuf, vSnd, nProgress, min(lim-nProgress, OTsPerIteration)); +#ifdef TIMING + gettimeofday(&tempEnd, NULL); + totalHshTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + nProgress += min(lim-nProgress, OTsPerIteration); + } + + vRcv.delCBitVector(); + Q.delCBitVector(); + for(uint32_t u = 0; u < m_nSndVals; u++) + seedbuf[u].delCBitVector(); + +#ifdef TIMING + cout << "Sender time benchmark for performing " << myNumOTs << " OTs on " << m_nBitLength << " bit strings" << endl; + cout << "Time needed for: " << endl; + cout << "\t Matrix Generation:\t" << totalMtxTime << " ms" << endl; + cout << "\t Sending Matrix:\t" << totalSndTime << " ms" << endl; + cout << "\t Transposing Matrix:\t" << totalTnsTime << " ms" << endl; + cout << "\t Hashing Matrix:\t" << totalHshTime << " ms" << endl; + cout << "\t Receiving Values:\t" << totalRcvTime << " ms" << endl; +#endif + + return TRUE; +} + +void OTExtension1ooNECCSender::BuildQMatrix(CBitVector& T, CBitVector& RcvBuf, uint32_t numblocks, uint8_t* ctr_buf) +{ + uint8_t* rcvbufptr = RcvBuf.GetArr(); + uint8_t* Tptr = T.GetArr(); + uint32_t* counter = (uint32_t*) ctr_buf; + uint32_t tempctr = *counter; + for (uint32_t k = 0; k < m_nCodeWordBits; k++, rcvbufptr += (m_nCodeWordBytes * numblocks)) + { + *counter = tempctr; + //one m_nCodeWordBytes / OTEXT_BLOCK_SIZE_uint8_tS = 2, thus 2 times the number of blocks + for(uint32_t b = 0; b < 2*numblocks; b++, (*counter)++, Tptr += OTEXT_BLOCK_SIZE_BYTES) { + m_cCrypto->encrypt(m_vKeySeeds + k, Tptr, ctr_buf, AES_BYTES);//MPC_AES_ENCRYPT(m_vKeySeeds + k, Tptr, ctr_buf); + } + if(m_nU.GetBit(k)) + { + T.XORBytes(rcvbufptr, k*m_nCodeWordBytes * numblocks, m_nCodeWordBytes * numblocks); + } + } +} + +void OTExtension1ooNECCSender::MaskInputs(CBitVector& Q, CBitVector* seedbuf, CBitVector* snd_buf, uint32_t ctr, uint32_t processedOTs) +{ + + //If OT-based PSI is performed, the hashing is skipped and the masking is called directly + if(m_bProtocol == RN_OT) { + m_fMaskFct->expandMask(Q, m_nU.GetArr(), ctr, processedOTs, m_nBitLength); //m_sSecParam.statbits + return; + //ncrfevals = 1; + } + + //HASH_CTX sha, shatmp; + uint8_t hash_buf[m_cCrypto->get_hash_bytes()]; + //SHA_BUFFER sha_buf; + + uint8_t** sbp = new uint8_t*[m_nSndVals]; + CBitVector mask(m_nCodeWordBits); + + uint32_t ncrfevals = m_nSndVals; + + + + for(uint32_t u = 0; u < m_nSndVals; u++) + sbp[u] = seedbuf[u].GetArr(); + + for(uint32_t i = ctr, j = 0; j(i)], 0, m_nCodeWordBytes); + else + mask.ANDBytes((uint8_t*) m_vCodeWords[u], 0, m_nCodeWordBytes); + + mask.XORBytes(Q.GetArr() + j * m_nCodeWordBytes, m_nCodeWordBytes); +#ifdef DEBUG_HASH_INPUT + cout << "hash input for i = " << i << " and u = " << u << ": "; + mask.PrintHex(); +#endif + //Q.XORBytes(mask.GetArr(), j * m_nCodeWordBytes, m_nCodeWordBytes); + m_cCrypto->hash_ctr(sbp[u], AES_BYTES, mask.GetArr(), m_nCodeWordBytes, i); + //sha = shatmp; + //MPC_HASH_UPDATE(&sha, mask.GetArr(), m_nCodeWordBytes); + //MPC_HASH_FINAL(&sha, hash_buf); +#ifdef DEBUG_HASH_OUTPUT + cout << "hash output for i = " << i << " and u = " << u << ": "; + for(uint32_t j = 0; j < AES_BYTES; j++) + cout << (hex) << (unsigned int) sbp[u][j]; + cout << (dec) << endl; +#endif + //memcpy(sbp[u], hash_buf, AES_BYTES); + sbp[u] += AES_BYTES; + } + } + + // Call expandMask to write data uint32_to snd_buf + cout << "Number of crf evals = " << ncrfevals << endl; + for(uint32_t u = 0; u < ncrfevals; u++) { + m_fMaskFct->expandMask(m_vValues[u], seedbuf[u].GetArr(), ctr, processedOTs, m_nBitLength); //m_sSecParam.statbits + } + + free(sbp); +} + + +bool OTExtension1ooNECCSender::verifyOT(uint32_t NumOTs) +{ + CSocket sock = m_nSockets[0]; + CBitVector vSnd(NUMOTBLOCKS*OTEXT_BLOCK_SIZE_BITS*m_nBitLength); + uint32_t processedOTBlocks, OTsPerIteration, nSnd; + uint8_t resp; + for(uint32_t i = 0, offset = 0; i < NumOTs;i+=OTsPerIteration, offset+=ceil_divide(m_nBitLength, 8)) + { + processedOTBlocks = min((uint32_t) NUMOTBLOCKS, ceil_divide(NumOTs-i, m_nCodeWordBits)); + OTsPerIteration = min(processedOTBlocks * m_nCodeWordBits, NumOTs-i); + nSnd = ceil_divide(OTsPerIteration * m_nBitLength, 8); + //cout << "copying " << nSnd << " bytes from " << CEIL_DIVIDE(i*m_nBitLength, 8) << ", for i = " << i << endl; + for(uint32_t u = 0; u < m_nSndVals; u++) { + vSnd.Copy(m_vValues[u].GetArr() + offset, 0, nSnd); + sock.Send(vSnd.GetArr(), nSnd); + } + sock.Receive(&resp, 1); + if(resp == 0x00) + { + cout << "OT verification unsuccessful" << endl; + return false; + } + } + vSnd.delCBitVector(); + cout << "OT Verification successful" << endl; + return true; +} + + diff --git a/src/util/ot/ot-extension-1oon-ecc.h b/src/util/ot/ot-extension-1oon-ecc.h new file mode 100644 index 0000000..707dac5 --- /dev/null +++ b/src/util/ot/ot-extension-1oon-ecc.h @@ -0,0 +1,129 @@ +/* + * Methods for the OT Extension routine + */ + +#ifndef __OT_EXTENSION_1N_H_ +#define __OT_EXTENSION_1N_H_ + +#include "../typedefs.h" +#include "../socket.h" +#include "../thread.h" +#include "../cbitvector.h" +#include "../crypto/crypto.h" +#include "maskingfunction.h" +#include "ot-extension.h" +#include "../crypto/crypto.h" + + + + +//TODO verification not working, fix +//#define ZDEBUG +//#define DEBUG_HASH_INPUT +//#define DEBUG_PRG_OUTPUT +//#define DEBUG_HASH_OUTPUT + + +class OTExtension1ooNECCSender : public OTExtSnd { +/* + * OT sender part + * Input: + * ret: returns the resulting bit representations. Has to initialized to a byte size of: nOTs * nSndVals * state.field_size + * + * CBitVector* values: holds the values to be transferred. If C_OT is enabled, the first dimension holds the value while the delta is written into the second dimension + * Output: was the execution successful? + */ + public: + OTExtension1ooNECCSender(uint32_t sndvals, uint32_t nOTs, uint32_t bitlength, crypto* crypt, CSocket* sock, CBitVector& U, uint8_t* keybytes, + CBitVector& x0, CBitVector& x1, uint8_t type) : OTExtSnd(sndvals, nOTs, bitlength, crypt, sock, U, keybytes, x0, x1, type, m_nCodeWordBits){ + InitAndReadCodeWord(&m_vCodeWords); + }; + + OTExtension1ooNECCSender(uint32_t nsndvals, crypto* crypt, CSocket* sock, CBitVector& U, uint8_t* keybytes) : + OTExtSnd(nsndvals, crypt, sock, U, keybytes, m_nCodeWordBits) { + InitAndReadCodeWord(&m_vCodeWords); + }; + + bool send(uint32_t numOTs, uint32_t bitlength, CBitVector* values, uint8_t type, uint32_t numThreads, MaskingFunction* maskfct); + bool send(uint32_t numThreads); + + bool OTSenderRoutine(uint32_t id, uint32_t myNumOTs); + void BuildQMatrix(CBitVector& T, CBitVector& RcvBuf, uint32_t blocksize, uint8_t* ctr); + void MaskInputs(CBitVector& Q, CBitVector* seedbuf, CBitVector* snd_buf, uint32_t ctr, uint32_t processedOTs); + bool verifyOT(uint32_t myNumOTs); + + private: + REGISTER_SIZE** m_vCodeWords; + + + class OTSenderThread : public CThread { + public: + OTSenderThread(uint32_t id, uint32_t nOTs, OTExtension1ooNECCSender* ext) {senderID = id; numOTs = nOTs; callback = ext; success = false;}; + ~OTSenderThread(){}; + void ThreadMain() {success = callback->OTSenderRoutine(senderID, numOTs);}; + private: + uint32_t senderID; + uint32_t numOTs; + OTExtension1ooNECCSender* callback; + bool success; + }; + +}; + + + +class OTExtension1ooNECCReceiver : public OTExtRec { +/* + * OT receiver part + * Input: + * nSndVals: perform a 1-out-of-nSndVals OT + * nOTs: the number of OTs that shall be performed + * choices: a vector containing nBaseOTs choices in the domain 0-(SndVals-1) + * ret: returns the resulting bit representations, Has to initialized to a byte size of: nOTs * state.field_size + * + * Output: was the execution successful? + */ + + public: + OTExtension1ooNECCReceiver(uint32_t nsndvals, uint32_t nOTs, uint32_t bitlength, crypto* crypt, CSocket* sock, + uint8_t* keybytes, CBitVector& choices, CBitVector& ret, uint8_t protocol) : + OTExtRec(nsndvals, nOTs, bitlength, crypt, sock, keybytes, choices, ret, protocol, m_nCodeWordBits) { + InitAndReadCodeWord(&m_vCodeWords); + }; + OTExtension1ooNECCReceiver(uint32_t nsndvals, crypto* crypt, CSocket* sock, uint8_t* keybytes) : + OTExtRec(nsndvals, crypt, sock, keybytes, m_nCodeWordBits) { + InitAndReadCodeWord(&m_vCodeWords); + }; + + + + bool receive(uint32_t numOTs, uint32_t bitlength, CBitVector& choices, CBitVector& ret, uint8_t type, + uint32_t numThreads, MaskingFunction* maskfct); + + bool receive(uint32_t numThreads); + bool OTReceiverRoutine(uint32_t id, uint32_t myNumOTs); + //void ReceiveAndProcess(CBitVector& vRcv, CBitVector& seedbuf, uint32_t id, uint32_t ctr, uint32_t lim); + void GenerateChoiceCodes(CBitVector& choicecodes, CBitVector& vSnd, uint32_t ctr, uint32_t lim); + void BuildMatrices(CBitVector& T, CBitVector& SndBuf, uint32_t numblocks, uint32_t ctr, uint8_t* ctr_buf); + void HashValues(CBitVector& T, CBitVector& seedbuf, uint32_t ctr, uint32_t lim); + bool verifyOT(uint32_t myNumOTs); + + + private: + REGISTER_SIZE** m_vCodeWords; + + class OTReceiverThread : public CThread { + public: + OTReceiverThread(uint32_t id, uint32_t nOTs, OTExtension1ooNECCReceiver* ext) {receiverID = id; numOTs = nOTs; callback = ext; success = false;}; + ~OTReceiverThread(){}; + void ThreadMain() {success = callback->OTReceiverRoutine(receiverID, numOTs);}; + private: + uint32_t receiverID; + uint32_t numOTs; + OTExtension1ooNECCReceiver* callback; + bool success; + }; + +}; + +#endif diff --git a/src/util/ot/ot-extension.cpp b/src/util/ot/ot-extension.cpp new file mode 100644 index 0000000..ae27fb6 --- /dev/null +++ b/src/util/ot/ot-extension.cpp @@ -0,0 +1,786 @@ +#include "ot-extension.h" + + + + +BOOL OTExtensionReceiver::receive(int numOTs, int bitlength, CBitVector& choices, CBitVector& ret, BYTE type, int numThreads, MaskingFunction* unmaskfct) +{ + m_nOTs = numOTs; + m_nBitLength = bitlength; + m_nChoices = choices; + m_nRet = ret; + m_bProtocol = type; + m_fMaskFct = unmaskfct; + return receive(numThreads); +}; + +//Initialize and start numThreads OTSenderThread +BOOL OTExtensionReceiver::receive(int numThreads) +{ + if(m_nOTs == 0) + return true; + + //The total number of OTs that is performed has to be a multiple of numThreads*Z_REGISTER_BITS + int internal_numOTs = CEIL_DIVIDE(PadToRegisterSize(m_nOTs), numThreads); + + //BYTE go; + //Wait for the signal of the corresponding sender thread + //sock.Receive(&go, 1); + + //Create temporary result buf to which the threads write their temporary masks + m_vTempOTMasks.Create(internal_numOTs * numThreads * m_nBitLength); + + vector rThreads(numThreads); + for(int i = 0; i < numThreads; i++) + { + rThreads[i] = new OTReceiverThread(i, internal_numOTs, this); + rThreads[i]->Start(); + } + + if(m_bProtocol != R_OT && m_bProtocol != OCRS_OT) + { + ReceiveAndProcess(numThreads); + } + + for(int i = 0; i < numThreads; i++) + { + rThreads[i]->Wait(); + } + m_nCounter += m_nOTs; + + for(int i = 0; i < numThreads; i++) + delete rThreads[i]; + + if(m_bProtocol == R_OT || m_bProtocol == OCRS_OT) { + m_nRet.Copy(m_vTempOTMasks.GetArr(), 0, CEIL_DIVIDE(m_nOTs * m_nBitLength, 8)); + m_vTempOTMasks.delCBitVector(); + } + + +#ifdef VERIFY_OT + //Wait for the signal of the corresponding sender thread + BYTE finished = 0x01; + m_nSockets[0].Send(&finished, 1); + + verifyOT(m_nOTs); +#endif + + + return true; +} + + + +BOOL OTExtensionReceiver::OTReceiverRoutine(int id, int myNumOTs) +{ + //cout << "Thread " << id << " started" << endl; + int myStartPos = id * myNumOTs; + int i = myStartPos, nProgress = myStartPos; + int RoundWindow = 2; + int roundctr = 0; + + myNumOTs = min(myNumOTs + myStartPos, m_nOTs) - myStartPos; + int lim = myStartPos+myNumOTs; + + int processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(myNumOTs, OTEXT_BLOCK_SIZE_BITS)); + int OTsPerIteration = processedOTBlocks * OTEXT_BLOCK_SIZE_BITS; + int OTwindow = NUMOTBLOCKS*OTEXT_BLOCK_SIZE_BITS*RoundWindow; + CSocket sock = m_nSockets[id]; + + //counter variables + int numblocks = CEIL_DIVIDE(myNumOTs, OTsPerIteration); + int nSize; + + // The receive buffer + CBitVector vRcv; + if(m_bProtocol == G_OT) + vRcv.Create(OTsPerIteration * m_nBitLength * m_nSndVals); + else if(m_bProtocol == C_OT || m_bProtocol == S_OT) + vRcv.Create(OTsPerIteration * m_nBitLength); + + // A temporary part of the T matrix + CBitVector T(OTEXT_BLOCK_SIZE_BITS * OTsPerIteration); + + // The send buffer + CBitVector vSnd(m_nSymSecParam * OTsPerIteration); + + // A temporary buffer that stores the resulting seeds from the hash buffer + //TODO: Check for some maximum size + CBitVector seedbuf(OTwindow*AES_KEY_BITS);// = new CBitVector[RoundWindow]; + //for(int j = 0; j < RoundWindow; j++) + // seedbuf[j].Create(OTwindow * AES_KEY_BITS); + + + + BYTE ctr_buf[AES_BYTES] = {0}; + int* counter = (int*) ctr_buf; + (*counter) = myStartPos + m_nCounter; + +#ifdef OTTiming + double totalMtxTime = 0, totalTnsTime = 0, totalHshTime = 0, totalRcvTime = 0, totalSndTime = 0; + timeval tempStart, tempEnd; +#endif + + while( i < lim ) + { + processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(lim-i, OTEXT_BLOCK_SIZE_BITS)); + OTsPerIteration = processedOTBlocks * OTEXT_BLOCK_SIZE_BITS; + nSize = (m_nSymSecParam>>3) * OTsPerIteration; + +#ifdef OTTiming + gettimeofday(&tempStart, NULL); +#endif + BuildMatrices(T, vSnd, processedOTBlocks, i, ctr_buf); +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalMtxTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + T.EklundhBitTranspose(OTEXT_BLOCK_SIZE_BITS, OTsPerIteration); +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalTnsTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + //cout << "offset: " << (AES_KEY_BYTES * (i-nProgress))<< ", i = " << i << ", nprogress = " << nProgress << ", otwindow = " << OTwindow << endl; + HashValues(T, seedbuf, i, min(lim-i, OTsPerIteration)); +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalHshTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + + //cout << "Sending " << nSize << " Bytes " << endl; + sock.Send( vSnd.GetArr(), nSize ); +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalSndTime += getMillies(tempStart, tempEnd); + gettimeofday(&tempStart, NULL); +#endif + i+=min(lim-i, OTsPerIteration); + +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalRcvTime += getMillies(tempStart, tempEnd); +#endif + vSnd.Reset(); + } + + T.delCBitVector(); + vSnd.delCBitVector(); + vRcv.delCBitVector(); + seedbuf.delCBitVector(); + +#ifdef OTTiming + cout << "Receiver time benchmark for performing " << myNumOTs << " OTs on " << m_nBitLength << " bit strings" << endl; + cout << "Time needed for: " << endl; + cout << "\t Matrix Generation:\t" << totalMtxTime << " ms" << endl; + cout << "\t Sending Matrix:\t" << totalSndTime << " ms" << endl; + cout << "\t Transposing Matrix:\t" << totalTnsTime << " ms" << endl; + cout << "\t Hashing Matrix:\t" << totalHshTime << " ms" << endl; + cout << "\t Receiving Values:\t" << totalRcvTime << " ms" << endl; +#endif +#ifndef BATCH + cout << "Receiver finished successfully" << endl; +#endif + //sleep(1); + return TRUE; +} + + + +void OTExtensionReceiver::BuildMatrices(CBitVector& T, CBitVector& SndBuf, int numblocks, int ctr, BYTE* ctr_buf) +{ + int* counter = (int*) ctr_buf; + int tempctr = (*counter); + + BYTE* Tptr = T.GetArr(); + BYTE* sndbufptr = SndBuf.GetArr(); + int ctrbyte = ctr/8; + for(int k = 0; k < m_nSymSecParam; k++) + { + (*counter) = tempctr; + for(int b = 0; b < numblocks; b++, (*counter)++) + { + MPC_AES_ENCRYPT(m_vKeySeedMtx + 2*k, Tptr, ctr_buf); + Tptr+=OTEXT_BLOCK_SIZE_BYTES; + + MPC_AES_ENCRYPT(m_vKeySeedMtx + (2*k) + 1, sndbufptr, ctr_buf); + sndbufptr+=OTEXT_BLOCK_SIZE_BYTES; + } + SndBuf.XORBytesReverse(m_nChoices.GetArr()+ctrbyte, k*OTEXT_BLOCK_SIZE_BYTES * numblocks, OTEXT_BLOCK_SIZE_BYTES * numblocks); + } + SndBuf.XORBytes(T.GetArr(), 0, OTEXT_BLOCK_SIZE_BYTES*numblocks*m_nSymSecParam); +} + + + +void OTExtensionReceiver::HashValues(CBitVector& T, CBitVector& seedbuf, int ctr, int processedOTs) +{ + BYTE* Tptr = T.GetArr(); + BYTE* bufptr = seedbuf.GetArr();//m_vSeedbuf.GetArr() + ctr * AES_KEY_BYTES;//seedbuf.GetArr(); + + HASH_CTX sha; + BYTE hash_buf[SHA1_BYTES]; + + for(int i = ctr; i < ctr+processedOTs; i++, Tptr+=OTEXT_BLOCK_SIZE_BYTES, bufptr+=AES_KEY_BYTES) + { + if((m_bProtocol == S_OT || m_bProtocol == OCRS_OT) && m_nChoices.GetBitNoMask(i) == 0) + { + continue; + } + + //for(hash_ctr = 0; hash_ctr < numhashiters; hash_ctr++, sha_buf.data+=SHA1_BYTES) + //{ +#ifdef FIXED_KEY_AES_HASHING + FixedKeyHashing(m_kCRFKey, bufptr, Tptr, hash_buf, i, m_nSymSecParam>>3); +#else + MPC_HASH_INIT(&sha); + MPC_HASH_UPDATE(&sha, (BYTE*) &i, sizeof(i)); + //OTEXT_HASH_UPDATE(&sha, (BYTE*) &hash_ctr, sizeof(hash_ctr)); + MPC_HASH_UPDATE(&sha, Tptr, m_nSymSecParam>>3); + MPC_HASH_FINAL(&sha, hash_buf); + //} + memcpy(bufptr, hash_buf, AES_KEY_BYTES); +#endif + + + //m_nRet.SetBits(hash_buf, i * m_nBitLength, m_nBitLength); + } + + // + m_fMaskFct->expandMask(m_vTempOTMasks, seedbuf.GetArr(), ctr, processedOTs, m_nBitLength); +} + + +//void OTExtensionReceiver::ReceiveAndProcess(CBitVector& vRcv, CBitVector& seedbuf, int id, int ctr, int processedOTs) +void OTExtensionReceiver::ReceiveAndProcess(int numThreads) +{ + int progress = 0; + int threadOTs = CEIL_DIVIDE(PadToRegisterSize(m_nOTs), numThreads); + int processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(threadOTs, OTEXT_BLOCK_SIZE_BITS)); + int OTsPerIteration = processedOTBlocks * OTEXT_BLOCK_SIZE_BITS; + int processedOTs; + int OTid; + int rcvbytes; + CBitVector vRcv; + +#ifdef OTTiming + double totalRcvTime = 0; + timeval tempStart, tempEnd; +#endif + + if(m_bProtocol == G_OT) + vRcv.Create(OTsPerIteration * m_nBitLength * m_nSndVals); + else if(m_bProtocol == C_OT || m_bProtocol == S_OT) + vRcv.Create(OTsPerIteration * m_nBitLength); + + while(progress < m_nOTs) + { + //cout << "Waiting for block " << endl; + + + m_nSockets[0].Receive((BYTE*) &OTid, sizeof(int)); + //cout << "Processing blockid " << OTid; + m_nSockets[0].Receive((BYTE*) &processedOTs, sizeof(int)); + //cout << " with " << processedOTs << " OTs "; + rcvbytes = CEIL_DIVIDE(processedOTs * m_nBitLength, 8); + if(m_bProtocol == G_OT) + rcvbytes = rcvbytes*m_nSndVals; + //cout << "Receiving " << rcvbytes << " bytes" << endl; + rcvbytes = m_nSockets[0].Receive(vRcv.GetArr(), rcvbytes); + +#ifdef OTTiming + gettimeofday(&tempStart, NULL); +#endif + //cout << "unmask" << endl; + m_fMaskFct->UnMask(OTid, processedOTs, m_nChoices, m_nRet, vRcv, m_vTempOTMasks, m_bProtocol); +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalRcvTime += getMillies(tempStart, tempEnd); +#endif + progress += processedOTs; + } + +#ifdef OTTiming + cout << "Total time spent processing received data: " << totalRcvTime << endl; +#endif + + vRcv.delCBitVector(); +} + +BOOL OTExtensionReceiver::verifyOT(int NumOTs) +{ + CSocket sock = m_nSockets[0]; + CBitVector vRcvX0(NUMOTBLOCKS*OTEXT_BLOCK_SIZE_BITS*m_nBitLength); + CBitVector vRcvX1(NUMOTBLOCKS*OTEXT_BLOCK_SIZE_BITS*m_nBitLength); + CBitVector* Xc; + int processedOTBlocks, OTsPerIteration; + int bytelen = CEIL_DIVIDE(m_nBitLength, 8); + BYTE* tempXc = new BYTE[bytelen]; + BYTE* tempRet = new BYTE[bytelen]; + BYTE resp; + for(int i = 0; i < NumOTs;) + { + processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(NumOTs-i, OTEXT_BLOCK_SIZE_BITS)); + //OTsPerIteration = processedOTBlocks * Z_REGISTER_BITS; + OTsPerIteration = min(processedOTBlocks * OTEXT_BLOCK_SIZE_BITS, NumOTs-i); + sock.Receive(vRcvX0.GetArr(), CEIL_DIVIDE(m_nBitLength * OTsPerIteration, 8)); + sock.Receive(vRcvX1.GetArr(), CEIL_DIVIDE(m_nBitLength * OTsPerIteration, 8)); + for(int j = 0; j < OTsPerIteration && i < NumOTs; j++, i++) + { + if(m_nChoices.GetBitNoMask(i) == 0) Xc = &vRcvX0; + else Xc = &vRcvX1; + + Xc->GetBits(tempXc, j*m_nBitLength, m_nBitLength); + m_nRet.GetBits(tempRet, i*m_nBitLength, m_nBitLength); + for(int k = 0; k < bytelen; k++) + { + if(tempXc[k] != tempRet[k]) + { + cout << "Error at position i = " << i << ", k = " << k << ", with X" << (hex) << (unsigned int) m_nChoices.GetBitNoMask(i) + << " = " << (unsigned int) tempXc[k] << " and res = " << (unsigned int) tempRet[k] << (dec) << endl; + resp = 0x00; + sock.Send(&resp, 1); + return false; + } + } + } + resp = 0x01; + sock.Send(&resp, 1); + } + delete[] tempXc; + delete[] tempRet; + + vRcvX0.delCBitVector(); + vRcvX1.delCBitVector(); + + cout << "OT Verification successful" << endl; + return true; +} + + + +BOOL OTExtensionSender::send(int numOTs, int bitlength, CBitVector& x0, CBitVector& x1, BYTE type, + int numThreads, MaskingFunction* maskfct) +{ + m_nOTs = numOTs; + m_nBitLength = bitlength; + m_vValues[0] = x0; + m_vValues[1] = x1; + m_bProtocol = type; + m_fMaskFct = maskfct; + return send(numThreads); +} + + +//Initialize and start numThreads OTSenderThread +BOOL OTExtensionSender::send(int numThreads) +{ + if(m_nOTs == 0) + return true; + + //The total number of OTs that is performed has to be a multiple of numThreads*Z_REGISTER_BITS + int numOTs = CEIL_DIVIDE(PadToRegisterSize(m_nOTs), numThreads); + m_nBlocks = 0; + m_lSendLock = new CLock; + + + vector sThreads(numThreads); + + //BYTE go; + //sock.Send(&go, 1); + + for(int i = 0; i < numThreads; i++) + { + sThreads[i] = new OTSenderThread(i, numOTs, this); + sThreads[i]->Start(); + } + + if(m_bProtocol != R_OT && m_bProtocol != OCRS_OT) + { + SendBlocks(numThreads); + } + + for(int i = 0; i < numThreads; i++) + { + sThreads[i]->Wait(); + } + m_nCounter += m_nOTs; + + for(int i = 0; i < numThreads; i++) + delete sThreads[i]; + +#ifdef VERIFY_OT + BYTE finished; + m_nSockets[0].Receive(&finished, 1); + + verifyOT(m_nOTs); +#endif + +/* cout << "OT0 val= "; + m_vValues[0].PrintBinary(); + cout << "OT1 val= "; + m_vValues[1].PrintBinary();*/ + + return true; +} + + +//BOOL OTsender(int nSndVals, int nOTs, int startpos, CSocket& sock, CBitVector& U, AES_KEY* vKeySeeds, CBitVector* values, BYTE* seed) +BOOL OTExtensionSender::OTSenderRoutine(int id, int myNumOTs) +{ + CSocket sock = m_nSockets[id]; + + int nProgress; + int myStartPos = id * myNumOTs; + int processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(myNumOTs, OTEXT_BLOCK_SIZE_BITS)); + int OTsPerIteration = processedOTBlocks * OTEXT_BLOCK_SIZE_BITS; + + myNumOTs = min(myNumOTs + myStartPos, m_nOTs) - myStartPos; + int lim = myStartPos+myNumOTs; + + //TODO: Check if this works: + if(m_bProtocol == S_OT || m_bProtocol == OCRS_OT) + m_nSndVals = 1; + + // The vector with the received bits + CBitVector vRcv(m_nSymSecParam * OTsPerIteration); + + // Holds the reply that is sent back to the receiver + int numsndvals = 2; + CBitVector* vSnd; + + /*if(m_bProtocol == G_OT) numsndvals = 2; + else if (m_bProtocol == C_OT || m_bProtocol == S_OT) numsndvals = 1; + else numsndvals = 0;*/ + + CBitVector* seedbuf = new CBitVector[m_nSndVals]; + for(int u = 0; u < m_nSndVals; u++) + seedbuf[u].Create(OTsPerIteration* AES_KEY_BITS); +#ifdef ZDEBUG + cout << "seedbuf size = " < 0) free(vSnd); + +#ifdef OTTiming + cout << "Sender time benchmark for performing " << myNumOTs << " OTs on " << m_nBitLength << " bit strings" << endl; + cout << "Time needed for: " << endl; + cout << "\t Matrix Generation:\t" << totalMtxTime << " ms" << endl; + cout << "\t Sending Matrix:\t" << totalSndTime << " ms" << endl; + cout << "\t Transposing Matrix:\t" << totalTnsTime << " ms" << endl; + cout << "\t Hashing Matrix:\t" << totalHshTime << " ms" << endl; + cout << "\t Receiving Values:\t" << totalRcvTime << " ms" << endl; +#endif + +#ifndef BATCH + cout << "Sender finished successfully" << endl; +#endif + return TRUE; +} + +void OTExtensionSender::BuildQMatrix(CBitVector& T, CBitVector& RcvBuf, int numblocks, BYTE* ctr_buf) +{ + BYTE* rcvbufptr = RcvBuf.GetArr(); + BYTE* Tptr = T.GetArr(); + int dummy; + int* counter = (int*) ctr_buf; + int tempctr = *counter; + for (int k = 0; k < m_nSymSecParam; k++, rcvbufptr += (OTEXT_BLOCK_SIZE_BYTES * numblocks)) + { + *counter = tempctr; + for(int b = 0; b < numblocks; b++, (*counter)++, Tptr += OTEXT_BLOCK_SIZE_BYTES) + { + MPC_AES_ENCRYPT(m_vKeySeeds + k, Tptr, ctr_buf); + } + if(m_nU.GetBit(k)) + { + T.XORBytes(rcvbufptr, k*OTEXT_BLOCK_SIZE_BYTES * numblocks, OTEXT_BLOCK_SIZE_BYTES * numblocks); + } + } +} + +void OTExtensionSender::MaskInputs(CBitVector& Q, CBitVector* seedbuf, CBitVector* snd_buf, int ctr, int processedOTs) +{ + int numhashiters = CEIL_DIVIDE(m_nBitLength, SHA1_BITS); + HASH_CTX sha, shatmp; + + BYTE hash_buf[SHA1_BYTES]; + //SHA_BUFFER sha_buf; + BYTE* Qptr = Q.GetArr(); + + BYTE** sbp = new BYTE*[m_nSndVals]; + + for(int u = 0; u < m_nSndVals; u++) + sbp[u] = seedbuf[u].GetArr(); + + for(int i = ctr, j = 0; j>3); + + + if(u == 1 || m_bProtocol == S_OT || m_bProtocol == OCRS_OT) + Q.XORBytes(m_nU.GetArr(), j * OTEXT_BLOCK_SIZE_BYTES, m_nSymSecParam>>3); + +#ifdef FIXED_KEY_AES_HASHING + //AES_KEY_CTX* aeskey, BYTE* outbuf, BYTE* inbuf, BYTE* tmpbuf, int id, int bytessecparam + FixedKeyHashing(m_kCRFKey, sbp[u], Q.GetArr() + j * OTEXT_BLOCK_SIZE_BYTES, hash_buf, i, m_nSymSecParam>>3); +#else + sha = shatmp; + MPC_HASH_UPDATE(&sha, Q.GetArr()+j * OTEXT_BLOCK_SIZE_BYTES, m_nSymSecParam>>3); + MPC_HASH_FINAL(&sha, hash_buf); + + memcpy(sbp[u], hash_buf, AES_KEY_BYTES); +#endif + + //cout << ((unsigned int) sbp[u][0] & 0x01); + sbp[u] += AES_KEY_BYTES; + + if(m_bProtocol == S_OT || m_bProtocol == OCRS_OT) + { + u=m_nSndVals-1; + } + } + } + + if(m_bProtocol == S_OT || m_bProtocol == OCRS_OT) + { + m_fMaskFct->expandMask(snd_buf[0], seedbuf[0].GetArr(), 0, processedOTs, m_nBitLength); + return; + } + + //Two calls to expandMask, both writing into snd_buf + for(int u = 0; u < m_nSndVals; u++) + m_fMaskFct->expandMask(snd_buf[u], seedbuf[u].GetArr(), 0, processedOTs, m_nBitLength); +} + +void OTExtensionSender::ProcessAndEnqueue(CBitVector* snd_buf, int id, int progress, int processedOTs) +{ + //cout << "processed OTs: " << processedOTs << endl; + m_fMaskFct->Mask(progress, processedOTs, m_vValues, snd_buf, m_bProtocol); + + if(m_bProtocol == R_OT) + return; + + OTBlock* block = new OTBlock; + int bufsize = CEIL_DIVIDE(processedOTs * m_nBitLength, 8); + + block->blockid = progress; + block->processedOTs = processedOTs; + + + if(m_bProtocol == G_OT) + { + block->snd_buf = new BYTE[bufsize<<1]; + memcpy(block->snd_buf, snd_buf[0].GetArr(), bufsize); + memcpy(block->snd_buf+bufsize, snd_buf[1].GetArr(), bufsize); + } + else if(m_bProtocol == C_OT) + { + block->snd_buf = new BYTE[bufsize]; + memcpy(block->snd_buf, snd_buf[1].GetArr(), bufsize); + } + else if(m_bProtocol == S_OT) + { + block->snd_buf = new BYTE[bufsize]; + memcpy(block->snd_buf, snd_buf[0].GetArr(), bufsize); + } + + + m_lSendLock->Lock(); + //Lock this part if multiple threads are used! + if(m_nBlocks == 0) + { + m_sBlockHead = block; + m_sBlockTail = block; + } else { + m_sBlockTail->next = block; + m_sBlockTail = block; + } + m_nBlocks++; + m_lSendLock->Unlock(); +} + + +void OTExtensionSender::SendBlocks(int numThreads) +{ + int progress = 0; + OTBlock* tempBlock; + +#ifdef OTTiming + double totalTnsTime = 0; + timeval tempStart, tempEnd; +#endif + + while(progress < m_nOTs) + { + if(m_nBlocks > 0) + { +#ifdef OTTiming + gettimeofday(&tempStart, NULL); +#endif + tempBlock = m_sBlockHead; + if(m_bProtocol == G_OT) + { + m_nSockets[0].Send((BYTE*) &(tempBlock->blockid), sizeof(int)); + m_nSockets[0].Send((BYTE*) &(tempBlock->processedOTs), sizeof(int)); + m_nSockets[0].Send(tempBlock->snd_buf, 2*CEIL_DIVIDE((tempBlock->processedOTs) * m_nBitLength, 8)); + } + else if(m_bProtocol == C_OT) + { + m_nSockets[0].Send((BYTE*) &(tempBlock->blockid), sizeof(int)); + m_nSockets[0].Send((BYTE*) &(tempBlock->processedOTs), sizeof(int)); + m_nSockets[0].Send(tempBlock->snd_buf, CEIL_DIVIDE((tempBlock->processedOTs) * m_nBitLength, 8)); + } + else if(m_bProtocol == S_OT) + { + m_nSockets[0].Send((BYTE*) &(tempBlock->blockid), sizeof(int)); + m_nSockets[0].Send((BYTE*) &(tempBlock->processedOTs), sizeof(int)); + m_nSockets[0].Send(tempBlock->snd_buf, CEIL_DIVIDE((tempBlock->processedOTs) * m_nBitLength, 8)); + } + //Lock this part + m_sBlockHead = m_sBlockHead->next; + + m_lSendLock->Lock(); + m_nBlocks--; + m_lSendLock->Unlock(); + + progress += tempBlock->processedOTs; + + delete tempBlock->snd_buf; + delete tempBlock; + +#ifdef OTTiming + gettimeofday(&tempEnd, NULL); + totalTnsTime += getMillies(tempStart, tempEnd); +#endif + } + } +#ifdef OTTiming + cout << "Total time spent transmitting data: " << totalTnsTime << endl; +#endif +} + + + +BOOL OTExtensionSender::verifyOT(int NumOTs) +{ + CSocket sock = m_nSockets[0]; + CBitVector vSnd(NUMOTBLOCKS*OTEXT_BLOCK_SIZE_BITS*m_nBitLength); + int processedOTBlocks, OTsPerIteration; + int bytelen = CEIL_DIVIDE(m_nBitLength, 8); + int nSnd; + BYTE resp; + for(int i = 0; i < NumOTs;i+=OTsPerIteration) + { + processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(NumOTs-i, OTEXT_BLOCK_SIZE_BITS)); + OTsPerIteration = min(processedOTBlocks * OTEXT_BLOCK_SIZE_BITS, NumOTs-i); + nSnd = CEIL_DIVIDE(OTsPerIteration * m_nBitLength, 8); + //cout << "copying " << nSnd << " bytes from " << CEIL_DIVIDE(i*m_nBitLength, 8) << ", for i = " << i << endl; + vSnd.Copy(m_vValues[0].GetArr() + CEIL_DIVIDE(i*m_nBitLength, 8), 0, nSnd); + sock.Send(vSnd.GetArr(), nSnd); + vSnd.Copy(m_vValues[1].GetArr() + CEIL_DIVIDE(i*m_nBitLength, 8), 0, nSnd); + sock.Send(vSnd.GetArr(), nSnd); + sock.Receive(&resp, 1); + if(resp == 0x00) + { + cout << "OT verification unsuccessful" << endl; + return false; + } + } + vSnd.delCBitVector(); + cout << "OT Verification successful" << endl; + return true; +} + + diff --git a/src/util/ot/ot-extension.h b/src/util/ot/ot-extension.h new file mode 100644 index 0000000..2307175 --- /dev/null +++ b/src/util/ot/ot-extension.h @@ -0,0 +1,284 @@ +/* + * Methods for the OT Extension routine + */ + +#ifndef __OT_EXTENSION_H_ +#define __OT_EXTENSION_H_ + +#include "../typedefs.h" +#include "../socket.h" +#include "../thread.h" +#include "../cbitvector.h" +#include "../crypto/crypto.h" +#include "maskingfunction.h" + + +//#define DEBUG +//#define FIXED_KEY_AES_HASHING +//#define VERIFY_OT + +const uint8_t G_OT = 0x01; +const uint8_t C_OT = 0x02; +const uint8_t R_OT = 0x03; +const uint8_t S_OT = 0x04; +const uint8_t OCRS_OT = 0x05; +const uint8_t RN_OT = 0x06; + + +typedef struct OTBlock_t { + uint32_t blockid; + uint32_t processedOTs; + uint8_t* snd_buf; + OTBlock_t* next; +} OTBlock; + +#define NUMOTBLOCKS 256 +#define REGISTER_BITS AES_BITS +#define REGISTER_BYTES AES_BYTES + + +static void InitAESKey(AES_KEY_CTX* ctx, uint8_t* keybytes, uint32_t numkeys) +{ + uint8_t* pBufIdx = keybytes; + for(uint32_t i=0; iget_seclvl().symbits; + m_vValues = (CBitVector*) malloc(sizeof(CBitVector) * nSndVals); + m_vKeySeeds = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX) * nbaseOTs); + InitAESKey(m_vKeySeeds, keybytes, nbaseOTs); + + m_lSendLock = new CLock; + + +#ifdef FIXED_KEY_AES_HASHING + m_kCRFKey = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX)); + m_cCrypto->init_aes_key(m_kCRFKey, XXLT.symbits, (uint8_t*) fixedkeyseed); + //MPC_AES_KEY_INIT(m_kCRFKey); + //MPC_AES_KEY_EXPAND(m_kCRFKey, fixedkeyseed); +#endif + }; + + ~OTExtSnd(){free(m_vKeySeeds);}; + bool send(uint32_t numOTs, uint32_t bitlength, CBitVector& s0, CBitVector& s1, uint8_t type, uint32_t numThreads, MaskingFunction* maskfct); + bool send(uint32_t numThreads); + + bool OTSenderRoutine(uint32_t id, uint32_t myNumOTs); + void BuildQMatrix(CBitVector& T, CBitVector& RcvBuf, uint32_t blocksize, uint8_t* ctr); + void ProcessAndEnqueue(CBitVector* snd_buf, uint32_t id, uint32_t progress, uint32_t processedOTs); + void SendBlocks(uint32_t numThreads); + void HashValues(CBitVector& Q, CBitVector* seedbuf, CBitVector* snd_buf, uint32_t ctr, uint32_t processedOTs); + bool verifyOT(uint32_t myNumOTs); + + + + protected: + uint8_t m_bProtocol; + uint32_t m_nSndVals; + uint32_t m_nOTs; + uint32_t m_nBitLength; + uint32_t m_nCounter; + uint32_t m_nBlocks; + uint32_t m_nSymSecParam; + CSocket* m_nSockets; + CBitVector m_nU; + CBitVector* m_vValues; + MaskingFunction* m_fMaskFct; + AES_KEY_CTX* m_vKeySeeds; + OTBlock* m_sBlockHead; + OTBlock* m_sBlockTail; + CLock* m_lSendLock; + crypto* m_cCrypto; +#ifdef FIXED_KEY_AES_HASH_OPRG + AES_KEY_CTX* m_kCRFKey; +#endif + + class OTSenderThread : public CThread { + public: + OTSenderThread(uint32_t id, uint32_t nOTs, OTExtSnd* ext) {senderID = id; numOTs = nOTs; callback = ext; success = false;}; + ~OTSenderThread(){}; + void ThreadMain() {success = callback->OTSenderRoutine(senderID, numOTs);}; + private: + uint32_t senderID; + uint32_t numOTs; + OTExtSnd* callback; + bool success; + }; + +}; + + + +class OTExtRec { +/* + * OT receiver part + * Input: + * nSndVals: perform a 1-out-of-nSndVals OT + * nOTs: the number of OTs that shall be performed + * choices: a vector containing nBaseOTs choices in the domain 0-(SndVals-1) + * ret: returns the resulting bit representations, Has to initialized to a byte size of: nOTs * state.field_size + * + * Output: was the execution successful? + */ + public: + OTExtensionReceiver(uint32_t nSndVals, uint32_t nOTs, uint32_t bitlength, crypto* crypt, CSocket* sock, + uint8_t* keybytes, CBitVector& choices, CBitVector& ret, uint8_t protocol, uint32_t nbaseOTs) { + Init(nSndVals, crypt, sock, keybytes, nbaseOTs); + //m_nSndVals = nSndVals; + m_nOTs = nOTs; + //m_nSockets = sock; + m_nChoices = choices; + m_nRet = ret; + //m_nSeed = seed; + m_nBitLength = bitlength; + m_eOTFlav = protocol; + //m_nCounter = 0; + //m_nSymSecParam = symsecparam; + //m_vKeySeedMtx = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX) * m_nSymSecParam * nSndVals); + //InitAESKey(m_vKeySeedMtx, keybytes, m_nSymSecParam * nSndVals); + }; + OTExtensionReceiver(uint32_t nSndVals, crypto* crypt, CSocket* sock, uint8_t* keybytes, uint32_t nbaseOTs) { + Init(nSndVals, crypt, sock, keybytes, nbaseOTs); + }; + + void Init(uint32_t nSndVals, crypto* crypt, CSocket* sock, uint8_t* keybytes, uint32_t nbaseOTs) { + m_nSndVals = nSndVals; + m_nSockets = sock; + //m_nKeySeedMtx = vKeySeedMtx; + m_cCrypto = crypt; + m_nSymSecParam = m_cCrypto->get_seclvl().symbits; + + + m_nCounter = 0; + m_vKeySeedMtx = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX) * nbaseOTs * nSndVals); + InitAESKey(m_vKeySeedMtx, keybytes, nbaseOTs * nSndVals); + + m_nSeed = (uint8_t*) malloc(sizeof(AES_BYTES)); // + m_cCrypto->gen_rnd(m_nSeed, AES_BYTES);//seed; + m_lRcvLock = new CLock; + +#ifdef FIXED_KEY_AES_HASHING + m_kCRFKey = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX)); + m_cCrypto->init_aes_key(m_kCRFKey, XXLT.symbits, (uint8_t*) fixedkeyseed); + //m_kCRFKey = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX)); + //MPC_AES_KEY_INIT(m_kCRFKey); + //MPC_AES_KEY_EXPAND(m_kCRFKey, fixedkeyseed); +#endif + } + + ~OTExtRec(){free(m_vKeySeedMtx); }; + + bool receive(uint32_t numOTs, uint32_t bitlength, CBitVector& choices, CBitVector& ret, uint8_t type, + uint32_t numThreads, MaskingFunction* maskfct); + + bool receive(uint32_t numThreads); + bool OTReceiverRoutine(uint32_t id, uint32_t myNumOTs); + //void ReceiveAndProcess(CBitVector& vRcv, CBitVector& seedbuf, uint32_t id, uint32_t ctr, uint32_t lim); + void ReceiveAndProcess(uint32_t numThreads); + void BuildMatrices(CBitVector& T, CBitVector& SndBuf, uint32_t numblocks, uint32_t ctr, uint8_t* ctr_buf); + void HashValues(CBitVector& T, CBitVector& seedbuf, uint32_t ctr, uint32_t lim); + bool verifyOT(uint32_t myNumOTs); + + protected: + uint8_t m_eOTFlav; + uint32_t m_nSndVals; + uint32_t m_nOTs; + uint32_t m_nBitLength; + uint32_t m_nCounter; + uint32_t m_nSymSecParam; + CSocket* m_nSockets; + CBitVector m_nChoices; + CBitVector m_nRet; + CBitVector m_vTempOTMasks; + uint8_t* m_nSeed; + MaskingFunction* m_fMaskFct; + AES_KEY_CTX* m_vKeySeedMtx; + crypto* m_cCrypto; + CLock* m_lRcvLock; +#ifdef FIXED_KEY_AES_HASHING + AES_KEY_CTX* m_kCRFKey; +#endif + + + class OTReceiverThread : public CThread { + public: + OTReceiverThread(uint32_t id, uint32_t nOTs, OTExtRec* ext) {receiverID = id; numOTs = nOTs; callback = ext; success = false;}; + ~OTReceiverThread(){}; + void ThreadMain() {success = callback->OTReceiverRoutine(receiverID, numOTs);}; + private: + uint32_t receiverID; + uint32_t numOTs; + OTExtRec* callback; + bool success; + }; + +}; + +#ifdef FIXED_KEY_AES_HASHING +inline void FixedKeyHashing(AES_KEY_CTX* aeskey, uint8_t* outbuf, uint8_t* inbuf, uint8_t* tmpbuf, uint32_t id, uint32_t bytessecparam) { + memset(tmpbuf, 0, AES_BYTES); + memcpy(tmpbuf, (uint8_t*) (&id), sizeof(uint32_t)); + for(uint32_t i = 0; i < bytessecparam; i++) { + tmpbuf[i] = tmpbuf[i] ^ inbuf[i]; + } + + MPC_AES_ENCRYPT(aeskey, outbuf, tmpbuf); + + for(uint32_t i = 0; i < bytessecparam; i++) { + outbuf[i] = outbuf[i] ^ inbuf[i];//todo: optimize + } +} +#endif + +#endif /* __OT_EXTENSION_H_ */ diff --git a/src/util/ot/xormasking.h b/src/util/ot/xormasking.h new file mode 100644 index 0000000..b9bd771 --- /dev/null +++ b/src/util/ot/xormasking.h @@ -0,0 +1,155 @@ +/* + * XORMasking.h + * + * Created on: May 13, 2013 + * Author: mzohner + */ + +#ifndef XORMASKING_H_ +#define XORMASKING_H_ + +#include "maskingfunction.h" + +class XORMasking : public MaskingFunction +{ +public: + XORMasking(int bitlength, crypto* crypt){init(bitlength, crypt); }; + XORMasking(int bitlength, crypto* crypt, CBitVector& delta) { m_vDelta = δ init(bitlength, crypt);}; + ~XORMasking(){}; + + + void init(int bitlength, crypto* crypt) + { + m_nBitLength = bitlength; + m_cCrypto = crypt; + } + + void Mask(uint32_t progress, uint32_t processedOTs, CBitVector* values, CBitVector* snd_buf, uint8_t protocol) + { + uint32_t nsndvals = 2; + + if(protocol == G_OT) + { + snd_buf[0].XORBytes(values[0].GetArr() + ceil_divide(progress * m_nBitLength, 8), (uint64_t) 0, ceil_divide(((uint64_t) processedOTs) * m_nBitLength, 8)); + snd_buf[1].XORBytes(values[1].GetArr() + ceil_divide(progress * m_nBitLength, 8), (uint64_t) 0, ceil_divide(((uint64_t) processedOTs) * m_nBitLength, 8)); + } + else if(protocol == C_OT) + { + values[0].SetBytes(snd_buf[0].GetArr(), ceil_divide(progress * m_nBitLength, 8), ceil_divide(processedOTs * m_nBitLength, 8));//.SetBits(hash_buf, i*m_nBitLength, m_nBitLength); + uint64_t bitPos = ((uint64_t) progress) * m_nBitLength; + uint64_t length = ((uint64_t) processedOTs) * m_nBitLength; + uint64_t bytePos = ceil_divide(bitPos, 8); + + //cout << "Performing masking for " << bytePos << " and " << bitPos << " to " << length << "(" << m_nBitLength << ", " << processedOTs << ")"<< endl; + values[1].SetBits(values[0].GetArr() + bytePos, bitPos, length); + values[1].XORBits(m_vDelta->GetArr() + bytePos, bitPos, length); + snd_buf[1].XORBits(values[1].GetArr() + bytePos, (uint64_t) 0, length); + } + else if(protocol == R_OT) + { + values[0].SetBytes(snd_buf[0].GetArr(), ceil_divide(progress * m_nBitLength, 8), ceil_divide(processedOTs * m_nBitLength, 8)); + values[1].SetBytes(snd_buf[1].GetArr(), ceil_divide(progress * m_nBitLength, 8), ceil_divide(processedOTs * m_nBitLength, 8)); + } + /*int bitPos = progress * m_nBitLength; + int length = processedOTs * m_nBitLength; + int bytePos = CEIL_DIVIDE(bitPos, 8); + + //cout << "Performing masking for " << bytePos << " and " << bitPos << " to " << length << "(" << m_nBitLength << ", " << processedOTs << ")"<< endl; + values[1].SetBits(values[0].GetArr() + bytePos, bitPos, length); + values[1].XORBits(m_vDelta->GetArr() + bytePos, bitPos, length); + + snd_buf.XORBits(values[1].GetArr() + bytePos, 0, length);*/ + }; + + //output already has to contain the masks + void UnMask(uint32_t progress, uint32_t processedOTs, CBitVector& choices, CBitVector& output, CBitVector& rcv_buf, CBitVector& tmpmask, uint8_t protocol) + { + uint32_t bytelen = ceil_divide(m_nBitLength, 8); + uint32_t gprogress = progress * bytelen; + //int gprogress = progress * m_nBitLength; + uint32_t lim = progress + processedOTs; + + if(protocol == G_OT) + { + for(uint32_t u, i= progress, offset = processedOTs * bytelen, l = 0; i < lim; i++, gprogress+=bytelen, l+=bytelen) + { + //TODO make this working for single bits + u = (int) choices.GetBitNoMask(i); + output.SetXOR(rcv_buf.GetArr() + (u * offset) + l, tmpmask.GetArr() + gprogress, gprogress, bytelen); + //output.SetBit(gprogress, tmpmask.GetBit(l)); + //output.XORBit(gprogress, rcv_buf.GetBit(u * offset + l)); + } + + } + else if (protocol == C_OT || protocol == S_OT) + { + int gprogress = progress * bytelen; + output.Copy(tmpmask.GetArr() + gprogress, gprogress, bytelen * processedOTs); + for(uint32_t i = progress, l = 0; i < lim; i++, l+=bytelen, gprogress+=bytelen) + { + if(choices.GetBitNoMask(i)) + { + //TODO make this working for single bits + output.XORBytes(rcv_buf.GetArr() + l, gprogress, (int) bytelen); + //output.XORBitsPosOffset(rcv_buf.GetArr(), l, progress*m_nBitLength, m_nBitLength); + } + } + } + else if(protocol == R_OT) + { + //The seed expansion has already been performed, so do nothing + } + }; + + + void expandMask(CBitVector& out, uint8_t* sbp, uint32_t offset, uint32_t processedOTs, uint32_t bitlength) + { + + if(bitlength <= m_cCrypto->get_aes_key_bytes()) + { + for(uint32_t i = 0; i< processedOTs; i++, sbp+=m_cCrypto->get_aes_key_bytes()) + { + // cout << "Setting bits from " << (offset + i) * bitlength << " with " << bitlength << " len " << endl; + //cout << "Byte: " << ((unsigned int) sbp[0]) << ", bitlenh = " << bitlength << ", pos = " << (offset + i) * bitlength << ", "; + + out.SetBits(sbp, (offset + i) * bitlength, bitlength); + //out.PrintBinary(); + + } + //cout << "Out = "<< endl; + //out.PrintHex(); + } + else + { + uint8_t m_bBuf[AES_BYTES]; + uint8_t ctr_buf[AES_BYTES] = {0}; + uint32_t counter = *((uint32_t*) ctr_buf); + AES_KEY_CTX tkey; + //MPC_AES_KEY_INIT(&tkey); + for(uint32_t i = 0, rem; i< processedOTs; i++, sbp+=m_cCrypto->get_aes_key_bytes()) + { + //MPC_AES_KEY_EXPAND(&tkey, sbp); + m_cCrypto->init_aes_key(&tkey, sbp); + for(counter = 0; counter < bitlength/AES_BITS; counter++) + { + m_cCrypto->encrypt(&tkey, m_bBuf, ctr_buf, AES_BYTES);//MPC_AES_ENCRYPT(&tkey, m_bBuf, ctr_buf); + out.SetBits(m_bBuf, (offset+ i) * bitlength + (counter*AES_BITS), AES_BITS); + } + //the final bits + //cout << "bits: " << (counter*AES_BITS) << ", bitlength: " << m_nBitLength << endl; + if((rem = bitlength - (counter*AES_BITS)) > 0) + { + m_cCrypto->encrypt(&tkey, m_bBuf, ctr_buf, AES_BYTES);//MPC_AES_ENCRYPT(&tkey, m_bBuf, ctr_buf); + out.SetBits(m_bBuf, (offset + i) * bitlength + (counter*AES_BITS), rem); + } + } + } + } + +private: + CBitVector* m_vDelta; + int m_nBitLength; + crypto* m_cCrypto; +}; + +#endif /* XORMASKING_H_ */ diff --git a/src/util/ot/xorrgbfmasking.h b/src/util/ot/xorrgbfmasking.h new file mode 100644 index 0000000..460cbcf --- /dev/null +++ b/src/util/ot/xorrgbfmasking.h @@ -0,0 +1,97 @@ +/* + * XORBFMasking.h + * + * Created on: October 22, 2013 + * Author: mzohner + */ + + +#ifndef XORRGBFMASKING_H_ +#define XORRGBFMASKING_H_ + +#include "maskingfunction.h" + +#define RGBF_SERVER 0x00 +#define RGBF_CLIENT 0x01 + +inline bool GetBitRGBF(BYTE* data, int idx){ + // return (filter->data[(idx+filter->leadingZeroes) >> 3] & (1 << (7-((idx+filter->leadingZeroes) & 7))))==0?0:1; + return !!(data[idx >> 3] & (1 << (7-(idx & 7)))); +}; + +//A masking function for the random garbled Bloom filter protocol +class XORRGBFMasking : public MaskingFunction +{ +public: + XORRGBFMasking(int bitlength, uint8_t id, uint8_t* choices, int leadingZeros) + {init(bitlength); m_bID = id; m_vChoices.AttachBuf(choices, bitlength); m_nLeadingZeros = leadingZeros;}; + ~XORRGBFMasking(){}; + + + void init(int bitlength) + { + if(!(bitlength>>3)) + { + cerr << "BitLength must be a multiple of 8!" << endl; + exit(0); + } + m_nByteLength = bitlength/8; + } + + + void Mask(int progress, int processedOTs, CBitVector* values, CBitVector* snd_buf, BYTE protocol) + { + //A hack write data into a fixed-size 2 dimensional out-bitvector for the GBF PSI protocl + BYTE** outptr = ((BYTE**) (values[0].GetArr()))+progress; + BYTE** limptr = outptr+processedOTs; + BYTE* srcptr = snd_buf[0].GetArr(); + BYTE* data = m_vChoices.GetArr(); + for(int i = progress+m_nLeadingZeros, j; outptr>3; + //for(int i = offset; i < offset+processedOTs; srcptr++, i++) + for(int i = offset+m_nLeadingZeros; outptr>3); + } + } + +private: + uint8_t** m_vDelta; + int m_nByteLength; + uint8_t m_bID; + CBitVector m_vChoices; + int m_nLeadingZeros; +}; + +#endif /* XORRGBFMASKING_H_ */ diff --git a/src/util/socket.h b/src/util/socket.h new file mode 100644 index 0000000..cfcc907 --- /dev/null +++ b/src/util/socket.h @@ -0,0 +1,274 @@ +//socket.h + +#ifndef __SOCKET_H__BY_SGCHOI +#define __SOCKET_H__BY_SGCHOI + +#include "typedefs.h" + +#define TRACK_COMMUNICATION + +class CSocket +{ +public: + CSocket(){ + m_hSock = INVALID_SOCKET; +#ifdef TRACK_COMMUNICATION + bytes_sent = 0; + bytes_received = 0; +#endif + } + ~CSocket(){ } + //~CSocket(){ cout << "Closing Socket!" << endl; Close(); } + +#ifdef TRACK_COMMUNICATION + uint64_t get_bytes_sent() { return bytes_sent; }; + uint64_t get_bytes_received() { return bytes_received; }; +#endif + +public: + bool Socket() + { + bool success = false; + + #ifdef WIN32 + static bool s_bInit = FALSE; + + if (!s_bInit) { + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + WSAStartup(wVersionRequested, &wsaData); + s_bInit = TRUE; + } + #endif + + Close(); + + success = (m_hSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET; + + return success; + + } + + void Close() + { + if( m_hSock == INVALID_SOCKET ) return; + + #ifdef WIN32 + shutdown(m_hSock, SD_SEND); + closesocket(m_hSock); + #else + shutdown(m_hSock, SHUT_WR); + close(m_hSock); + #endif + + m_hSock = INVALID_SOCKET; + } + + void AttachFrom(CSocket& s) + { + m_hSock = s.m_hSock; + } + + void Detach() + { + m_hSock = INVALID_SOCKET; + } + +public: + string GetIP() + { + sockaddr_in addr; + uint32_t addr_len = sizeof(addr); + + if (getsockname(m_hSock, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) return ""; + return inet_ntoa(addr.sin_addr); + } + + + uint16_t GetPort() + { + sockaddr_in addr; + uint32_t addr_len = sizeof(addr); + + if (getsockname(m_hSock, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) return 0; + return ntohs(addr.sin_port); + } + + bool Bind(uint16_t nPort=0, const char* ip = "") + { + // Bind the socket to its port + sockaddr_in sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + sockAddr.sin_family = AF_INET; + + if( strcmp(ip, "") ) + { + int on = 1; + setsockopt(m_hSock, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on)); + + sockAddr.sin_addr.s_addr = inet_addr(ip); + + if (sockAddr.sin_addr.s_addr == INADDR_NONE) + { + hostent* phost; + phost = gethostbyname(ip); + if (phost != NULL) + sockAddr.sin_addr.s_addr = ((in_addr*)phost->h_addr)->s_addr; + else + return false; + } + } + else + { + sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + + sockAddr.sin_port = htons(nPort); + + return bind(m_hSock, (sockaddr *) &sockAddr, sizeof(sockaddr_in)) >= 0; + } + + bool Listen(int nQLen = 5) + { + return listen(m_hSock, nQLen) >= 0; + } + + bool Accept(CSocket& sock) + { + sock.m_hSock = accept(m_hSock, NULL, 0); + if( sock.m_hSock == INVALID_SOCKET ) return false; + + return true; + } + + bool Connect(const char* ip, uint16_t port, int64_t lTOSMilisec = -1) + { + //cout << "Socket " << m_hSock << " connected" << endl; + sockaddr_in sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + sockAddr.sin_family = AF_INET; + sockAddr.sin_addr.s_addr = inet_addr(ip); + + if (sockAddr.sin_addr.s_addr == INADDR_NONE) + { + hostent* lphost; + lphost = gethostbyname(ip); + if (lphost != NULL) + sockAddr.sin_addr.s_addr = ((in_addr*)lphost->h_addr)->s_addr; + else + return false; + } + + sockAddr.sin_port = htons(port); + +#ifdef WIN32 + + DWORD dw = 100000; + + if( lTOSMilisec > 0 ) + { + setsockopt(m_hSock, SOL_SOCKET, SO_RCVTIMEO, (char*) &lTOSMilisec, sizeof(lTOSMilisec)); + } + + int ret = connect(m_hSock, (sockaddr*)&sockAddr, sizeof(sockAddr)); + + if( ret >= 0 && lTOSMilisec > 0 ) + setsockopt(m_hSock, SOL_SOCKET, SO_RCVTIMEO, (char*) &dw, sizeof(dw)); + +#else + + timeval tv; + + if( lTOSMilisec > 0 ) + { + tv.tv_sec = lTOSMilisec/1000; + tv.tv_usec = (lTOSMilisec%1000)*1000; + + setsockopt(m_hSock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + } + + int ret = connect(m_hSock, (sockaddr*)&sockAddr, sizeof(sockAddr)); + + if( ret >= 0 && lTOSMilisec > 0 ) + { + tv.tv_sec = 100000; + tv.tv_usec = 0; + + setsockopt(m_hSock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + } + +#endif + return ret >= 0; + } + + int Receive(void* pBuf, int nLen, int nFlags = 0) + { + //cout << "Socket " << m_hSock << " (" << (unsigned long long) this << ") receiving " << nLen << " bytes" << endl; + char* p = (char*) pBuf; + int n = nLen; + int ret = 0; + while( n > 0 ) + { + ret = recv(m_hSock, p, n, 0); +#ifdef WIN32 + if( ret <= 0 ) + { + return ret; + } +#else + if( ret < 0 ) + { + if( errno == EAGAIN ) + { + cerr << "socket recv eror: EAGAIN" << endl; + SleepMiliSec(200); + continue; + } + else + { + cerr << "socket recv error: " << errno << endl; + perror("Socket error "); + return ret; + } + } + else if (ret == 0) + { + return ret; + } +#endif + + p += ret; + n -= ret; + } + +#ifdef TRACK_COMMUNICATION + bytes_received += ((uint64_t) nLen); + //cout << "bytes_received = " << bytes_received << endl; +#endif + return nLen; + } + + int Send(const void* pBuf, int nLen, int nFlags = 0) + { + //cout << "Socket " << m_hSock << " (" << (unsigned long long) this << ") sending " << nLen << " bytes" << endl; +#ifdef TRACK_COMMUNICATION + bytes_sent+= ((uint64_t) nLen); + //cout << "bytes_sent = " << bytes_sent << endl; +#endif + return send(m_hSock, (char*)pBuf, nLen, nFlags); + } + +private: + SOCKET m_hSock; +#ifdef TRACK_COMMUNICATION + uint64_t bytes_sent; + uint64_t bytes_received; +#endif + +}; + + +#endif //SOCKET_H__BY_SGCHOI + diff --git a/src/util/thread.h b/src/util/thread.h new file mode 100644 index 0000000..3aedb26 --- /dev/null +++ b/src/util/thread.h @@ -0,0 +1,255 @@ +// thread.h by sgchoi@cs.umd.edu + +#ifndef __THREAD_H__BY_SGCHOI +#define __THREAD_H__BY_SGCHOI + +#include "typedefs.h" + +#ifdef WIN32 + +#include + +class CEvent +{ +// Constructor +public: + CEvent(bool bManualReset = FALSE, bool bInitialSet = FALSE) + { + m_hHandle = ::CreateEvent(0, bManualReset, bInitialSet, 0); + } + + ~CEvent() + { + CloseHandle(m_hHandle); + } + +// Operations +public: + bool Set(){ return SetEvent(m_hHandle); } + bool Reset(){ return ResetEvent(m_hHandle); } + bool Wait(){ return WaitForSingleObject(m_hHandle, INFINITE) == WAIT_OBJECT_0; } + +private: + HANDLE m_hHandle; +}; + + +///////////////////////////////////////////////////////////////////////////// +// CLock + + +// Operations +class CLock +{ +// Constructor +public: + CLock(){ InitializeCriticalSection(&m_cs); } + ~CLock(){ DeleteCriticalSection(&m_cs); } + +public: + void Lock(){ EnterCriticalSection(&m_cs); } + void Unlock(){ LeaveCriticalSection(&m_cs); } + +private: + CRITICAL_SECTION m_cs; +}; + +class CThread +{ +public: + CThread(){m_bRunning = FALSE; m_hHandle = NULL;} + virtual ~CThread(){ if(m_hHandle != NULL) CloseHandle(m_hHandle);} + +public: + bool Start() + { + m_bRunning = TRUE; + m_hHandle = CreateThread(0, 0, ThreadMainHandler, this,0,0); + if( m_hHandle == NULL ) + m_bRunning = FALSE; + + return m_bRunning; + } + + bool Wait() + { + if( !m_bRunning ) return TRUE; + return WaitForSingleObject(m_hHandle, INFINITE) == WAIT_OBJECT_0; + } + + bool Kill() + { + if( !m_bRunning) return TRUE; + + m_bRunning = !(TerminateThread(m_hHandle, 0)); + return !m_bRunning; + } + + bool IsRunning() + { + return m_bRunning; + } + + +protected: + virtual void ThreadMain() = 0; + + static DWORD __stdcall ThreadMainHandler( void* p ) + { + CThread* pThis = (CThread*) p; + pThis->ThreadMain(); + pThis->m_bRunning = FALSE; + return 0; + } + +protected: + bool m_bRunning; + HANDLE m_hHandle; +}; + + +#else // NOT WIN32 +#include +class CThread +{ +public: + CThread(){m_bRunning = false; } + virtual ~CThread(){} + +public: + bool Start() + { + m_bRunning = !pthread_create(&m_pThread, NULL, + ThreadMainHandler, (void*) this); + return m_bRunning; + } + + bool Wait() + { + if( !m_bRunning ) return true; + return pthread_join(m_pThread, NULL)==0; + } + + bool Kill() + { + if( !m_bRunning) return true; + pthread_exit(NULL); + return true; + } + + bool IsRunning() + { + return m_bRunning; + } + +protected: + virtual void ThreadMain() = 0; + static void* ThreadMainHandler( void* p ) + { + CThread* pThis = (CThread*) p; + pThis->ThreadMain(); + pThis->m_bRunning = false; + return 0; + } + +protected: + bool m_bRunning; + pthread_t m_pThread; +}; + + +class CLock +{ +// Constructor +public: + CLock(){ pthread_mutex_init(&m_mtx, NULL); } + ~CLock(){ pthread_mutex_destroy(&m_mtx); } + +public: + void Lock(){ pthread_mutex_lock(&m_mtx);} + void Unlock(){ pthread_mutex_unlock(&m_mtx); } + +private: + pthread_mutex_t m_mtx; +}; + + + +class CEvent +{ +// Constructor +public: + CEvent(bool bManualReset = false, bool bInitialSet = false) + { + pthread_mutex_init(&m_mtx, NULL); + pthread_cond_init(&m_cnd, NULL); + m_bManual = bManualReset; + m_bSet = bInitialSet; + } + + ~CEvent() + { + pthread_mutex_destroy(&m_mtx); + pthread_cond_destroy(&m_cnd); + } + +// Operations +public: + bool Set() + { + pthread_mutex_lock(&m_mtx); + if(!m_bSet) + { + m_bSet = true; + + pthread_cond_signal(&m_cnd); + } + + pthread_mutex_unlock(&m_mtx); + return true; + } + + bool Wait() + { + pthread_mutex_lock( &m_mtx ); + + while(!m_bSet) + { + pthread_cond_wait( &m_cnd, &m_mtx ); + } + + if ( !m_bManual ) m_bSet = false; + pthread_mutex_unlock( &m_mtx ); + return true; + } + + bool Reset() + { + pthread_mutex_lock( &m_mtx ); + m_bSet = false; + pthread_mutex_unlock( &m_mtx ); + return true; + } +private: + pthread_cond_t m_cnd; + pthread_mutex_t m_mtx; + bool m_bManual; + bool m_bSet; + }; + +#endif //WIN32 + + + +class CGrabLock +{ +public: + CGrabLock(CLock& l):lock(l){ lock.Lock(); } + ~CGrabLock(){ lock.Unlock(); } +public: + CLock& lock; +}; + +#endif //__THREAD_H__BY_SGCHOI + + diff --git a/src/util/typedefs.h b/src/util/typedefs.h new file mode 100644 index 0000000..3d54c6d --- /dev/null +++ b/src/util/typedefs.h @@ -0,0 +1,136 @@ +/* + * typedefs.h + * + * Created on: Jul 1, 2014 + * Author: mzohner + */ + +#ifndef TYPEDEFS_H_ +#define TYPEDEFS_H_ + +//#define DEBUG +#define BATCH +//#define TIMING + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; + + +enum field_type {P_FIELD, ECC_FIELD}; +enum role_type {SERVER, CLIENT}; + +#define MAX_REPLY_BITS 65536 //at most 2^16 bits may be sent in one go +#define ELEMENT_WINDOW 1024 +#define MAX_REPLY_BYTES MAX_REPLY_BITS/8 + +#define RETRY_CONNECT 1000 +#define CONNECT_TIMEO_MILISEC 10000 + + +#define OTEXT_BLOCK_SIZE_BITS 128 +#define OTEXT_BLOCK_SIZE_BYTES 16 + +#define VECTOR_INTERNAL_SIZE 8 + +#define MAX_INT (~0) +#if (MAX_INT == 0xFFFFFFFF) +#define MACHINE_SIZE_32 +typedef uint32_t REGISTER_SIZE; + +#elif (MAX_INT == 0xFFFFFFFFFFFFFFFF) +#define MACHINE_SIZE_64 +typedef unsigned long int REGISTER_SIZE; + +#else +#define MACHINE_SIZE_16 +typedef uint16_t REGISTER_SIZE; + +#endif + +#define LOG2_REGISTER_SIZE ceil_log2(sizeof(REGISTER_SIZE) << 3) + +#ifdef WIN32 +#include +#include + +typedef unsigned short USHORT; +typedef int socklen_t; +#pragma comment(lib, "wsock32.lib") + +#define SleepMiliSec(x) Sleep(x) + +#else //WIN32 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef int SOCKET; +#define INVALID_SOCKET -1 +typedef REGISTER_SIZE REGSIZE; + +#define SleepMiliSec(x) usleep((x)<<10) +#endif// WIN32 + +#define ceil_divide(x, y) ((x) > 0? ( ((x) - 1) / (y) )+1 : 0) +#define pad_to_multiple(x, y) (ceil_divide(x, y) * (y)) + +typedef struct securitylevel +{ + uint32_t statbits; + uint32_t symbits; + uint32_t ifcbits; + uint32_t eccpfbits; + uint32_t ecckcbits; +} seclvl; + + +static const seclvl ST = {40, 80, 1024, 160, 163}; +static const seclvl MT = {40, 112, 2048, 192, 233}; +static const seclvl LT = {40, 128, 3072, 256, 283}; +static const seclvl XLT = {40, 192, 7680, 384, 409}; +static const seclvl XXLT = {40, 256, 15360, 512, 571}; + +static int ceil_log2(int bits) { + if(bits == 1) return 1; + int targetlevel = 0, bitstemp = bits; + while (bitstemp >>= 1) ++targetlevel; + return targetlevel + ((1<>= 1) ++targetlevel; + return targetlevel; +} + + +// Timing routines +static double getMillies(timeval timestart, timeval timeend) +{ + long time1 = (timestart.tv_sec * 1000000) + (timestart.tv_usec ); + long time2 = (timeend.tv_sec * 1000000) + (timeend.tv_usec ); + + return (double)(time2-time1)/1000; +} + +#endif /* TYPEDEFS_H_ */