mirror of
https://github.com/encryptogroup/PSI.git
synced 2024-03-22 13:30:44 +08:00
Initial file upload
This commit is contained in:
parent
2ff1fb7e17
commit
0864e04217
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/externals/Miracl"]
|
||||
path = src/externals/Miracl
|
||||
url = git://github.com/CertiVox/Miracl.git
|
52
Makefile
Normal file
52
Makefile
Normal file
|
@ -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
|
52
Makefile~
Normal file
52
Makefile~
Normal file
|
@ -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
|
425
src/bench_psi.cpp
Normal file
425
src/bench_psi.cpp
Normal file
|
@ -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<CSocket> 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<CSocket> 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: ./"<<progname;
|
||||
for(i = 0; i < nops; i++) {
|
||||
cout << " -" << options[i].opt_name << " [" << options[i].help_str <<"]";
|
||||
}
|
||||
cout << endl << "Program exiting" << endl;
|
||||
}
|
||||
|
||||
|
||||
void print_bench_usage() {
|
||||
cout << "Usage: ./PSI_demo.exe -r [0 (server)/1 (client)] -f [input file] -n [num_elements (optional, default: all elements in file)]"
|
||||
<< " -a [ip_address (optional, default:localhost)] -t [enable detailed timings and no output printing (optional, default: off)]" << endl;
|
||||
cout << "Program exiting" << endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void print_demo_usage() {
|
||||
cout << "Usage: ./PSI_demo.exe -r [0 (server)/1 (client)] -f [input file] -n [num_elements (optional, default: all elements in file)]"
|
||||
<< " -a [ip_address (optional, default:localhost)] -t [enable detailed timings and no output printing (optional, default: off)]" << endl;
|
||||
cout << "Program exiting" << endl;
|
||||
exit(0);
|
||||
}
|
61
src/bench_psi.h
Normal file
61
src/bench_psi.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* bench_psi.h
|
||||
*
|
||||
* Created on: Nov 10, 2014
|
||||
* Author: mzohner
|
||||
*/
|
||||
|
||||
#ifndef BENCH_PSI_H_
|
||||
#define BENCH_PSI_H_
|
||||
|
||||
#include "pk-based/dh-psi.h"
|
||||
#include "ot-based/ot-psi.h"
|
||||
#include "thirdparty/shpsi.h"
|
||||
#include "naive-hashing/naive-psi.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
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_ */
|
1
src/externals/Miracl
vendored
Submodule
1
src/externals/Miracl
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit cff161bad6364548b361b63938a988db23f60c2a
|
196
src/hashing/cuckoo.cpp
Normal file
196
src/hashing/cuckoo.cpp
Normal file
|
@ -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 " <<i <<"!" << endl;
|
||||
//exit(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COUNT_FAILS
|
||||
if(fails > 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;
|
||||
}
|
60
src/hashing/cuckoo.h
Normal file
60
src/hashing/cuckoo.h
Normal file
|
@ -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_ */
|
216
src/hashing/hashing_util.h
Normal file
216
src/hashing/hashing_util.h
Normal file
|
@ -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<<hs->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_ */
|
154
src/hashing/kcuckoo3a.C
Normal file
154
src/hashing/kcuckoo3a.C
Normal file
|
@ -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 <K> <n> <r> <repeat> <seed for rng>
|
||||
// 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 <iostream>
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
#include "mt-real.c"
|
||||
#include <assert.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
*/
|
90
src/hashing/mt-real.c
Normal file
90
src/hashing/mt-real.c
Normal file
|
@ -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
|
||||
<matumoto@math.keio.ac.jp> know it.
|
||||
|
||||
Because of a machine-trouble, Matsumoto lost emails
|
||||
which arrived during May 28-29.
|
||||
*/
|
||||
|
||||
|
||||
#include<stdio.h>
|
||||
|
||||
/* 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<N; k++)
|
||||
ptgfsr[k] = (69069 * ptgfsr[k-1]) & 0xffffffff;
|
||||
}
|
||||
|
||||
double
|
||||
genrand()
|
||||
{
|
||||
unsigned long y;
|
||||
static int k = 1;
|
||||
static unsigned long mag01[2]={0x0, MATRIX_A};
|
||||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
|
||||
if(k == N){ /* generate N words at one time */
|
||||
int kk;
|
||||
for (kk=0;kk<N-M;kk++) {
|
||||
y = (ptgfsr[kk]&UPPER_MASK)|(ptgfsr[kk+1]&LOWER_MASK);
|
||||
ptgfsr[kk] = ptgfsr[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
}
|
||||
for (;kk<N-1;kk++) {
|
||||
y = (ptgfsr[kk]&UPPER_MASK)|(ptgfsr[kk+1]&LOWER_MASK);
|
||||
ptgfsr[kk] = ptgfsr[kk+(M-N)] ^ (y >> 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 );
|
||||
}
|
||||
|
178
src/hashing/simple_hashing.cpp
Normal file
178
src/hashing/simple_hashing.cpp
Normal file
|
@ -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);
|
||||
}
|
54
src/hashing/simple_hashing.h
Normal file
54
src/hashing/simple_hashing.h
Normal file
|
@ -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_ */
|
103
src/hashing/util.h
Normal file
103
src/hashing/util.h
Normal file
|
@ -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 <time.h>
|
||||
|
||||
|
||||
// elapsed CPU time see also /usr/include/sys/time.h
|
||||
inline double cpuTime()
|
||||
{
|
||||
return clock() * 1e-6;
|
||||
}
|
||||
|
||||
#endif
|
218
src/naive-hashing/naive-psi.cpp
Normal file
218
src/naive-hashing/naive-psi.cpp
Normal file
|
@ -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);
|
||||
}
|
60
src/naive-hashing/naive-psi.h
Normal file
60
src/naive-hashing/naive-psi.h
Normal file
|
@ -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 <glib.h>
|
||||
|
||||
|
||||
|
||||
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_ */
|
855
src/ot-based/ot-psi.cpp
Normal file
855
src/ot-based/ot-psi.cpp
Normal file
|
@ -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<CSocket> 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<uint64_t>(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; i<numbaseOTs; i++ ) //80 HF calls for the Naor Pinkas protocol
|
||||
{
|
||||
memcpy(keySeeds + i * crypt->get_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; i<numbaseOTs * 2; i++ )
|
||||
{
|
||||
memcpy(keyMtx + i * crypt->get_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_ctr<my_neles)
|
||||
intersect_ctr++;
|
||||
//cout << "Match found at " << tmpval[0] << endl;
|
||||
}
|
||||
} else {
|
||||
matches[intersect_ctr] = tmpval[0];
|
||||
if(intersect_ctr<my_neles)
|
||||
intersect_ctr++;
|
||||
//cout << "Match found at " << tmpval[0] << " for i = " << i << endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: workaround since the masks that are inserted into the hash table are too small and collisions occur
|
||||
if(intersect_ctr > my_neles) {
|
||||
cout << "more intersections than elements: " << intersect_ctr << " vs " << my_neles << endl;
|
||||
intersect_ctr = my_neles;
|
||||
}
|
||||
//assert(intersect_ctr <= my_neles);
|
||||
size_intersect = intersect_ctr;
|
||||
|
||||
//result = (uint8_t**) malloc(sizeof(uint8_t*));
|
||||
(*result) = (uint32_t*) malloc(sizeof(uint32_t) * size_intersect);
|
||||
memcpy(*result, matches, sizeof(uint32_t) * size_intersect);
|
||||
|
||||
//cout << "I found " << size_intersect << " intersecting elements" << endl;
|
||||
|
||||
free(matches);
|
||||
free(map);
|
||||
return size_intersect;
|
||||
}
|
||||
|
||||
void evaluate_crf(uint8_t* result, uint8_t* masks, uint32_t nelements, uint32_t elebytelen, crypto* crypt) {
|
||||
uint32_t i;
|
||||
AES_KEY_CTX aes_key;
|
||||
crypt->init_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);
|
||||
}
|
||||
|
93
src/ot-based/ot-psi.h
Normal file
93
src/ot-based/ot-psi.h
Normal file
|
@ -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 <algorithm>
|
||||
#include <glib.h>
|
||||
|
||||
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_ */
|
325
src/pk-based/dh-psi.cpp
Normal file
325
src/pk-based/dh-psi.cpp
Normal file
|
@ -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);
|
||||
}
|
69
src/pk-based/dh-psi.h
Normal file
69
src/pk-based/dh-psi.h
Normal file
|
@ -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 <glib.h>
|
||||
|
||||
|
||||
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_ */
|
329
src/thirdparty/shpsi.cpp
vendored
Normal file
329
src/thirdparty/shpsi.cpp
vendored
Normal file
|
@ -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;i<neles[0];i++) {
|
||||
#ifdef DEBUG
|
||||
cout << "Inserted item: " << (hex) << ((uint64_t*) csets[0])[2*i] << " "<< ((uint64_t*) csets[0])[2*i+1] << (dec) << endl;
|
||||
#endif
|
||||
g_hash_table_insert(map,(void*) &((uint64_t*)csets[0])[2*i], &(((uint64_t*)csets[0])[2*i+1]));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
g_hash_table_foreach( map, printKeyValue, NULL );
|
||||
#endif
|
||||
gettimeofday(&end, NULL);
|
||||
#ifdef TIMING
|
||||
cout << "Insertion took " << getMillies(begin, end) << " ms" << endl;
|
||||
#endif
|
||||
gettimeofday(&begin, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
cout << "Checking for duplicates " << endl;
|
||||
#endif
|
||||
for(i = 1; i < nclients; i++) {
|
||||
tmpmap = g_hash_table_new_full(
|
||||
g_int64_hash, g_int64_equal,
|
||||
NULL, // no cleanup for key
|
||||
NULL // cleanup value
|
||||
);
|
||||
for(j = 0; j < neles[i]; j++) {
|
||||
#ifdef DEBUG
|
||||
cout << "Checking for Key: " << (hex) << ((uint64_t*) csets[i])[2*j] << " "<< ((uint64_t*) csets[i])[2*j+1] << (dec) << endl;
|
||||
#endif
|
||||
if(g_hash_table_lookup_extended(map, (void*) &(((uint64_t*)csets[i])[2*j]),
|
||||
NULL, (void**) &tmpval) && (*tmpval == ((uint64_t*)csets[i])[2*j+1])) {
|
||||
#ifdef DEBUG
|
||||
cout << "Key was found" << endl;
|
||||
#endif
|
||||
g_hash_table_insert(tmpmap,(void*) &(((uint64_t*)csets[i])[2*j]),&(((uint64_t*)csets[i])[2*j+1]));
|
||||
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
cout << "Key not found" << endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//Delete map
|
||||
g_hash_table_destroy(map);
|
||||
map = tmpmap;
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
#ifdef TIMING
|
||||
cout << "Checking took " << getMillies(begin, end) << " ms" << endl;
|
||||
#endif
|
||||
gettimeofday(&begin, NULL);
|
||||
|
||||
intersectsize = g_hash_table_size(map);
|
||||
|
||||
//intersect = (uint8_t*) malloc(sizeof(uint8_t) * intersectsize * entrybytelen);
|
||||
|
||||
#ifdef DEBUG
|
||||
cout << "Intersection contains the elements: " << endl;
|
||||
#endif
|
||||
g_hash_table_iter_init (&iter, map);
|
||||
//Iterate over all key / element pairs and store them in the intersection
|
||||
while(g_hash_table_iter_next (&iter, (void**) &tmpkey, (void**) &tmpval)) {
|
||||
#ifdef DEBUG
|
||||
cout << (hex) << tmpkey[0] << " " << tmpval[0] << (dec)<< endl;
|
||||
#endif
|
||||
((uint64_t*) intersect)[ctr++] = tmpkey[0];
|
||||
((uint64_t*) intersect)[ctr++] = tmpval[0];
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
#ifdef TIMING
|
||||
cout << "Iterating took " << getMillies(begin, end) << " ms" << endl;
|
||||
#endif
|
||||
|
||||
g_hash_table_destroy(map);
|
||||
|
||||
//free(tmpval);
|
||||
//free(tmpkey);
|
||||
#ifdef DEBUG
|
||||
cout << "returning" << endl;
|
||||
#endif
|
||||
return intersectsize;
|
||||
}
|
||||
|
||||
|
||||
uint32_t client_routine(uint32_t neles, uint32_t elebytelen, uint8_t* elements,
|
||||
uint8_t** result, crypto* crypt, CSocket* socket, bool cardinality) {
|
||||
uint32_t maskbytelen = 16, intersectsize, i, j;
|
||||
uint8_t* masks = (uint8_t*) malloc(sizeof(uint8_t) * neles * maskbytelen);
|
||||
uint8_t* intersect = (uint8_t*) malloc(sizeof(uint8_t) * neles * maskbytelen);
|
||||
uint32_t* perm;
|
||||
uint32_t* invperm = (uint32_t*) malloc(sizeof(uint32_t) * neles);
|
||||
|
||||
uint32_t* tmpval = (uint32_t*) malloc(sizeof(uint32_t));
|
||||
GHashTable *map;
|
||||
|
||||
//crypto crypto(symsecbits, (uint8_t*) const_seed);
|
||||
|
||||
// cout << "Starting client with " << neles << " elements of " << (8*elebytelen) << "-bit length with server "
|
||||
// << address << ":" << port << endl;
|
||||
|
||||
CSocket* sockfd = socket;
|
||||
//connect(address, port, sockfd);
|
||||
sockfd->Send((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);
|
||||
}
|
||||
}
|
BIN
src/thirdparty/shpsi.exe
vendored
Executable file
BIN
src/thirdparty/shpsi.exe
vendored
Executable file
Binary file not shown.
55
src/thirdparty/shpsi.h
vendored
Normal file
55
src/thirdparty/shpsi.h
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* shpsi.h
|
||||
*
|
||||
* Created on: Jul 1, 2014
|
||||
* Author: mzohner
|
||||
*/
|
||||
|
||||
#ifndef SHPSI_H_
|
||||
#define SHPSI_H_
|
||||
|
||||
#include <glib.h>
|
||||
#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_ */
|
680
src/util/cbitvector.cpp
Normal file
680
src/util/cbitvector.cpp
Normal file
|
@ -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<<remlen)-1) << lowermask))) | ((temp << lowermask) & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
//cout << "Setting " << remlen << " bits with lowermask = " << lowermask << ", uppermask = " << uppermask << ", and temp = " << (unsigned int) temp << endl;
|
||||
m_pBits[posctr] = (m_pBits[posctr] & RESET_BIT_POSITIONS[lowermask]) | ((temp << lowermask) & 0xFF);
|
||||
m_pBits[posctr+1] = (m_pBits[posctr+1] & (~(((1<<(remlen-uppermask))-1)))) | (temp >> uppermask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBitVector::SetBitsToZero(int bitpos, int bitlen)
|
||||
{
|
||||
int firstlim = ceil_divide(bitpos, 8);
|
||||
int firstlen = ceil_divide(bitlen - (bitpos % 8), 8);
|
||||
for(int i = bitpos; i < firstlim; i++)
|
||||
{
|
||||
SetBitNoMask(i, 0);
|
||||
}
|
||||
if(bitlen > 7)
|
||||
{
|
||||
memset(m_pBits + firstlim, 0, firstlen);
|
||||
}
|
||||
for(int i = (firstlim + firstlen) << 8; i < bitpos + bitlen; i++)
|
||||
{
|
||||
SetBitNoMask(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBitVector::GetBits(uint8_t* p, uint64_t pos, uint64_t len)
|
||||
{
|
||||
if(len < 1 || (pos+len) > (uint64_t) m_nByteSize << 3)
|
||||
return;
|
||||
if(len == 1)
|
||||
{
|
||||
*p = GetBitNoMask(pos);
|
||||
return;
|
||||
}
|
||||
if(!((pos & 0x07) || (len & 0x07)))
|
||||
{
|
||||
GetBytes(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++)
|
||||
{
|
||||
p[i] = ((m_pBits[posctr] & GET_BIT_POSITIONS[lowermask]) >> lowermask) & 0xFF;
|
||||
p[i] |= (m_pBits[posctr+1] & GET_BIT_POSITIONS_INV[uppermask]) << uppermask;
|
||||
}
|
||||
int remlen = len & 0x07;
|
||||
if(remlen)
|
||||
{
|
||||
//temp = p[i] & GET_BIT_POSITIONS[remlen];
|
||||
if(remlen <= uppermask)
|
||||
{
|
||||
//cout << "Getting " << remlen << " lower bits with lowermask = " << lowermask << ", " << (unsigned int) m_pBits[posctr] << endl;
|
||||
p[i] = ((m_pBits[posctr] & (((1<<remlen)-1 << lowermask))) >> 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<<SHIFTVAL)-1)));
|
||||
}
|
||||
|
||||
template <class T> 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<<SHIFTVAL)-1)));
|
||||
}
|
||||
|
||||
//Generic bytewise XOR operation
|
||||
template <class T> 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<<SHIFTVAL)-1)));
|
||||
}
|
||||
|
||||
template <class T> 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<<SHIFTVAL)-1)));
|
||||
}
|
||||
template <class T> 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<int>(i) << ", ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < m_nNumElements; i++)
|
||||
{
|
||||
cout << "(";
|
||||
for(int j = 0; j < m_nNumElementsDimB-1; j++)
|
||||
{
|
||||
cout << Get2D<int>(i, j) << ", ";
|
||||
}
|
||||
cout << Get2D<int>(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));
|
||||
*rowbptr = ((*rowbptr & invmask) ^ ((temp_row & invmask)>>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)<<srcidx));
|
||||
}
|
||||
rowaptr+=destidx;
|
||||
rowbptr+=destidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(int i = LOG2_REGISTER_SIZE, j, swapoffset=1, dswapoffset; i < numiters; i++, srcidx*=2, swapoffset=swapoffset<<1) {
|
||||
destidx = offset*srcidx;
|
||||
dswapoffset = swapoffset << 1;
|
||||
rowaptr = (REGISTER_SIZE*) m_pBits;
|
||||
rowbptr = rowaptr + destidx-swapoffset;//ptr = temp_mat;
|
||||
|
||||
rounds = rows / (srcidx * 2);
|
||||
for(int j = 0; j < rows / (srcidx * 2); j++) {
|
||||
for(p = 0, lim = rowbptr+destidx; p < destidx && rowbptr < lim; p++, rowaptr++, rowbptr++) {
|
||||
if((p%dswapoffset >= 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 <columns/rows; i++) {
|
||||
rowbptr = (REGISTER_SIZE*) tempvec;
|
||||
rowbptr += (i * rowregsize);
|
||||
for(int j = 0; j < rows; j++, rowaptr+=rowregsize, rowbptr+=offset) {
|
||||
memcpy(rowaptr, rowbptr, rowbytesize);
|
||||
}
|
||||
}
|
||||
free(tempvec);
|
||||
}
|
||||
}
|
||||
|
||||
|
305
src/util/cbitvector.h
Normal file
305
src/util/cbitvector.h
Normal file
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* BitVector.h
|
||||
*
|
||||
* Created on: May 6, 2013
|
||||
* Author: mzohner
|
||||
*/
|
||||
|
||||
#ifndef CBITVECTOR_H_
|
||||
#define CBITVECTOR_H_
|
||||
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
#include "typedefs.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#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 <class T> void GetBytes(T* dst, T* src, T* lim);
|
||||
//template <class T> T Get(int pos, int len);
|
||||
template <class T> 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 <class T> void SetBytes(T* dst, T* src, T* lim);
|
||||
template <class T> 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 <class T> 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 <class T> 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 <class T> 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 <class T> T Get(int i){ return Get<T>(i*m_nElementLength, m_nElementLength);}
|
||||
template <class T> void Set(T val, int i){ Set<T>(val, i*m_nElementLength, m_nElementLength);}
|
||||
/*
|
||||
* The same as the above methods only for two-dimensional access
|
||||
*/
|
||||
template <class T> T Get2D(int i, int j){ return Get<T>((i * m_nNumElementsDimB + j) * m_nElementLength, m_nElementLength);}
|
||||
template <class T> void Set2D(T val, int i, int j){ Set<T>(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_ */
|
25
src/util/codewords.cpp
Normal file
25
src/util/codewords.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
*/
|
283
src/util/codewords.h
Normal file
283
src/util/codewords.h
Normal file
|
@ -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_
|
78
src/util/connection.cpp
Normal file
78
src/util/connection.cpp
Normal file
|
@ -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<RETRY_CONNECT; i++ ) {
|
||||
if( !sockfd.Socket() )
|
||||
goto connect_failure;
|
||||
if( sockfd.Connect( address, port, lTO)) {
|
||||
#ifdef DEBUG
|
||||
cout << "Connection established" << endl;
|
||||
#endif
|
||||
SleepMiliSec(10);
|
||||
return true;
|
||||
}
|
||||
SleepMiliSec(10);
|
||||
sockfd.Close();
|
||||
}
|
||||
|
||||
connect_failure:
|
||||
cout << " connection failed due to timeout!" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool listen(const char* address, uint16_t port, CSocket* sockfds, uint32_t nconnections) {
|
||||
#ifdef DEBUG
|
||||
cout << "Listening: " << address << ":" << port << endl;
|
||||
#endif
|
||||
uint32_t lid = nconnections-1;
|
||||
if( !sockfds[lid].Socket() ) {
|
||||
cerr << "Error: a socket could not be created " << endl;
|
||||
goto listen_failure;
|
||||
}
|
||||
if( !sockfds[lid].Bind(port,address) ) {
|
||||
cerr << "Error: a socket could not be bound" << endl;
|
||||
goto listen_failure;
|
||||
}
|
||||
if( !sockfds[lid].Listen() ) {
|
||||
cerr << "Error: could not listen on the socket " << endl;
|
||||
goto listen_failure;
|
||||
}
|
||||
|
||||
for( uint32_t i = 0; i < nconnections; i++ )
|
||||
{
|
||||
CSocket sock;
|
||||
if( !sockfds[lid].Accept(sock) ) {
|
||||
cerr << "Error: could not accept connection" << endl;
|
||||
goto listen_failure;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
cout << "Connection with " << i << "-th client established" << endl;
|
||||
#endif
|
||||
// locate the socket appropriately
|
||||
sockfds[i].AttachFrom(sock);
|
||||
sock.Detach();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
cout << "Listening finished" << endl;
|
||||
#endif
|
||||
return true;
|
||||
|
||||
listen_failure:
|
||||
cout << "Listen failed" << endl;
|
||||
return false;
|
||||
}
|
22
src/util/connection.h
Normal file
22
src/util/connection.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* connection.h
|
||||
*
|
||||
* Created on: Jul 1, 2014
|
||||
* Author: mzohner
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H__
|
||||
#define CONNECTION_H__
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "socket.h"
|
||||
#include <sstream>
|
||||
|
||||
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
|
409
src/util/crypto/crypto.cpp
Normal file
409
src/util/crypto/crypto.cpp
Normal file
|
@ -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);
|
||||
}*/
|
139
src/util/crypto/crypto.h
Normal file
139
src/util/crypto/crypto.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* crypto.h
|
||||
*
|
||||
* Created on: Jul 9, 2014
|
||||
* Author: mzohner
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_H_
|
||||
#define CRYPTO_H_
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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_ */
|
289
src/util/crypto/ecc-pk-crypto.cpp
Normal file
289
src/util/crypto/ecc-pk-crypto.cpp
Normal file
|
@ -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);
|
||||
|
||||
}
|
143
src/util/crypto/ecc-pk-crypto.h
Normal file
143
src/util/crypto/ecc-pk-crypto.h
Normal file
|
@ -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_ */
|
280
src/util/crypto/gmp-pk-crypto.cpp
Normal file
280
src/util/crypto/gmp-pk-crypto.cpp
Normal file
|
@ -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; u<m_numberOfElements; ++u) {
|
||||
mpz_mul(m_table[u], m_table[u-1], m_table[u-1]);
|
||||
mpz_mod(m_table[u], m_table[u], *field->get_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; u<m_numberOfElements; u++) {
|
||||
//if (bit(e,u)) {
|
||||
if(mpz_tstbit(*exp, u))
|
||||
{
|
||||
mpz_mul(*res, *res, m_table[u]);
|
||||
mpz_mod(*res, *res, *field->get_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);
|
||||
}
|
||||
}
|
118
src/util/crypto/gmp-pk-crypto.h
Normal file
118
src/util/crypto/gmp-pk-crypto.h
Normal file
|
@ -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 <gmp.h>
|
||||
|
||||
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_ */
|
88
src/util/crypto/pk-crypto.h
Normal file
88
src/util/crypto/pk-crypto.h
Normal file
|
@ -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_ */
|
BIN
src/util/miracl.a
Normal file
BIN
src/util/miracl.a
Normal file
Binary file not shown.
53
src/util/ot/baseOT.h
Normal file
53
src/util/ot/baseOT.h
Normal file
|
@ -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 <ctime>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <time.h>
|
||||
#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_ */
|
33
src/util/ot/maskingfunction.h
Normal file
33
src/util/ot/maskingfunction.h
Normal file
|
@ -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_ */
|
204
src/util/ot/naor-pinkas.cpp
Normal file
204
src/util/ot/naor-pinkas.cpp
Normal file
|
@ -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);
|
||||
}
|
26
src/util/ot/naor-pinkas.h
Normal file
26
src/util/ot/naor-pinkas.h
Normal file
|
@ -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
|
236
src/util/ot/opemasking.h
Normal file
236
src/util/ot/opemasking.h
Normal file
|
@ -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<uint32_t>((bit_id + u* m_nOTsPerElement) * 8, 8)], 0, m_nCodeWordBytes);
|
||||
mask.ANDBytes((uint8_t*) m_vCodeWords[m_vServerChoices.Get<uint32_t>((binoffset + bit_id + u* m_nOTsPerElement) * 8, 8)], 0, m_nCodeWordBytes);
|
||||
//cout << (hex) << m_vServerChoices[bin_id].Get<uint32_t>((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<uint32_t>((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<uint32_t>((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 */
|
624
src/util/ot/ot-extension-1oon-ecc.cpp
Normal file
624
src/util/ot/ot-extension-1oon-ecc.cpp
Normal file
|
@ -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<OTReceiverThread*> 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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<OTSenderThread*> 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 = " <<OTsPerIteration * AES_BITS << endl;
|
||||
#endif
|
||||
|
||||
// Contains the parts of the V matrix TOOD: replace OTEXT_BLOCK_SIZE_BITS by processedOTBlocks
|
||||
CBitVector Q(m_nCodeWordBits * OTsPerIteration);
|
||||
|
||||
// A dummy-buffer
|
||||
CBitVector* vSnd;
|
||||
|
||||
// A buffer that holds a counting value, required for a faster uint32_teraction with the AES calls
|
||||
uint8_t ctr_buf[AES_BYTES];
|
||||
memset(ctr_buf, 0, AES_BYTES);
|
||||
uint32_t* counter = (uint32_t*) ctr_buf;
|
||||
counter[0] = myStartPos + m_nCounter;
|
||||
|
||||
nProgress = myStartPos;
|
||||
|
||||
#ifdef TIMING
|
||||
double totalMtxTime = 0, totalTnsTime = 0, totalHshTime = 0, totalRcvTime = 0, totalSndTime = 0;
|
||||
timeval tempStart, tempEnd;
|
||||
#endif
|
||||
|
||||
while( nProgress < lim ) //do while there are still transfers missing
|
||||
{
|
||||
processedOTBlocks = min((uint32_t) NUMOTBLOCKS, ceil_divide(lim-nProgress, m_nCodeWordBits));
|
||||
OTsPerIteration = processedOTBlocks * m_nCodeWordBits;
|
||||
|
||||
#ifdef ZDEBUG
|
||||
cout << "Processing block " << nProgress << " with length: " << OTsPerIteration << endl;
|
||||
#endif
|
||||
|
||||
#ifdef TIMING
|
||||
gettimeofday(&tempStart, NULL);
|
||||
#endif
|
||||
//m_lSendLock->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<processedOTs; i++, j++)
|
||||
{
|
||||
//MPC_HASH_INIT(&sha);
|
||||
//MPC_HASH_UPDATE(&sha, (uint8_t*) &i, sizeof(i));
|
||||
//shatmp = sha;
|
||||
|
||||
for(uint32_t u = 0; u < ncrfevals; u++)
|
||||
{
|
||||
mask.Copy(m_nU.GetArr(), 0, m_nCodeWordBytes);
|
||||
if(m_bProtocol == RN_OT)
|
||||
mask.ANDBytes((uint8_t*) m_vCodeWords[m_vValues[1].Get<uint32_t>(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;
|
||||
}
|
||||
|
||||
|
129
src/util/ot/ot-extension-1oon-ecc.h
Normal file
129
src/util/ot/ot-extension-1oon-ecc.h
Normal file
|
@ -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
|
786
src/util/ot/ot-extension.cpp
Normal file
786
src/util/ot/ot-extension.cpp
Normal file
|
@ -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<OTReceiverThread*> 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<OTSenderThread*> 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 = " <<OTsPerIteration * AES_KEY_BITS << endl;
|
||||
#endif
|
||||
vSnd = new CBitVector[numsndvals];//(CBitVector*) malloc(sizeof(CBitVector) * numsndvals);
|
||||
for(int i = 0; i < numsndvals; i++)
|
||||
{
|
||||
vSnd[i].Create(OTsPerIteration * m_nBitLength);
|
||||
}
|
||||
|
||||
// Contains the parts of the V matrix TOOD: replace OTEXT_BLOCK_SIZE_BITS by processedOTBlocks
|
||||
CBitVector Q(OTEXT_BLOCK_SIZE_BITS * OTsPerIteration);
|
||||
|
||||
// A buffer that holds a counting value, required for a faster interaction with the AES calls
|
||||
BYTE ctr_buf[AES_BYTES];
|
||||
memset(ctr_buf, 0, AES_BYTES);
|
||||
int* counter = (int*) ctr_buf;
|
||||
counter[0] = myStartPos + m_nCounter;
|
||||
|
||||
nProgress = myStartPos;
|
||||
|
||||
#ifdef OTTiming
|
||||
double totalMtxTime = 0, totalTnsTime = 0, totalHshTime = 0, totalRcvTime = 0, totalSndTime = 0;
|
||||
timeval tempStart, tempEnd;
|
||||
#endif
|
||||
|
||||
while( nProgress < lim ) //do while there are still transfers missing
|
||||
{
|
||||
|
||||
processedOTBlocks = min(NUMOTBLOCKS, CEIL_DIVIDE(lim-nProgress, OTEXT_BLOCK_SIZE_BITS));
|
||||
OTsPerIteration = processedOTBlocks * OTEXT_BLOCK_SIZE_BITS;
|
||||
|
||||
#ifdef ZDEBUG
|
||||
cout << "Processing block " << nProgress << " with length: " << OTsPerIteration << endl;
|
||||
#endif
|
||||
|
||||
#ifdef OTTiming
|
||||
gettimeofday(&tempStart, NULL);
|
||||
#endif
|
||||
//cout << "Waiting for data" << endl;
|
||||
sock.Receive(vRcv.GetArr(), m_nSymSecParam*OTEXT_BLOCK_SIZE_BYTES * processedOTBlocks);
|
||||
// cout << "received data" << endl;
|
||||
#ifdef OTTiming
|
||||
gettimeofday(&tempEnd, NULL);
|
||||
totalRcvTime += getMillies(tempStart, tempEnd);
|
||||
gettimeofday(&tempStart, NULL);
|
||||
#endif
|
||||
BuildQMatrix(Q, vRcv, processedOTBlocks, ctr_buf);
|
||||
#ifdef OTTiming
|
||||
gettimeofday(&tempEnd, NULL);
|
||||
totalMtxTime += getMillies(tempStart, tempEnd);
|
||||
gettimeofday(&tempStart, NULL);
|
||||
#endif
|
||||
Q.EklundhBitTranspose(OTEXT_BLOCK_SIZE_BITS, OTsPerIteration);
|
||||
#ifdef OTTiming
|
||||
gettimeofday(&tempEnd, NULL);
|
||||
totalTnsTime += getMillies(tempStart, tempEnd);
|
||||
gettimeofday(&tempStart, NULL);
|
||||
#endif
|
||||
MaskInputs(Q, seedbuf, vSnd, nProgress, min(lim-nProgress, OTsPerIteration));
|
||||
#ifdef OTTiming
|
||||
gettimeofday(&tempEnd, NULL);
|
||||
totalHshTime += getMillies(tempStart, tempEnd);
|
||||
gettimeofday(&tempStart, NULL);
|
||||
#endif
|
||||
ProcessAndEnqueue(vSnd, id, nProgress, min(lim-nProgress, OTsPerIteration));
|
||||
#ifdef OTTiming
|
||||
gettimeofday(&tempEnd, NULL);
|
||||
totalSndTime += getMillies(tempStart, tempEnd);
|
||||
#endif
|
||||
nProgress += min(lim-nProgress, OTsPerIteration);
|
||||
}
|
||||
|
||||
vRcv.delCBitVector();
|
||||
Q.delCBitVector();
|
||||
for(int u = 0; u < m_nSndVals; u++)
|
||||
seedbuf[u].delCBitVector();
|
||||
|
||||
for(int i = 0; i < numsndvals; i++)
|
||||
vSnd[i].delCBitVector();
|
||||
if(numsndvals > 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<processedOTs; i++, j++)
|
||||
{
|
||||
if(m_bProtocol == OCRS_OT && m_vValues[0].GetBitNoMask(i) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef FIXED_KEY_AES_HASHING
|
||||
MPC_HASH_INIT(&sha);
|
||||
MPC_HASH_UPDATE(&sha, (BYTE*) &i, sizeof(i));
|
||||
shatmp = sha;
|
||||
#endif
|
||||
for(int u = 0; u < m_nSndVals; u++)
|
||||
{
|
||||
//omit zero possibility
|
||||
//if( || m_bProtocol == OCRS_OT)
|
||||
// Q.XORBytes(m_nU.GetArr(), j * OTEXT_BLOCK_SIZE_BYTES, m_nSymSecParam>>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;
|
||||
}
|
||||
|
||||
|
284
src/util/ot/ot-extension.h
Normal file
284
src/util/ot/ot-extension.h
Normal file
|
@ -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; i<numkeys; i++ )
|
||||
{
|
||||
EVP_CIPHER_CTX_init(ctx+i);
|
||||
EVP_EncryptInit_ex(ctx+i, EVP_aes_128_ecb(), NULL, pBufIdx, ZERO_IV);
|
||||
|
||||
pBufIdx += AES_BYTES;
|
||||
}
|
||||
}
|
||||
#ifdef FIXED_KEY_AES_HASHING
|
||||
static const uint8_t fixedkeyseed[2*AES_BYTES] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, \
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
|
||||
#endif
|
||||
|
||||
|
||||
class 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:
|
||||
OTExtensionSender(uint32_t nSndVals, uint32_t nOTs, uint32_t bitlength, crypto* crypt, CSocket* sock, CBitVector& U, uint8_t* keybytes,
|
||||
CBitVector& x0, CBitVector& x1, uint8_t type, uint32_t nbaseOTs) {
|
||||
Init(nSndVals, crypt, sock, U, keybytes, nbaseOTs);
|
||||
//m_nSndVals = nSndVals;
|
||||
m_nOTs = nOTs;
|
||||
//m_nSockets = sock;
|
||||
//m_nU = U;
|
||||
//m_vValues = (CBitVector*) malloc(sizeof(CBitVector) * 2);
|
||||
m_vValues[0] = x0;
|
||||
m_vValues[1] = x1;
|
||||
m_nBitLength = bitlength;
|
||||
m_eOTFlav = type;
|
||||
//m_nCounter = 0;
|
||||
//m_nSymSecParam = symsecparam;
|
||||
//m_vKeySeeds = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX) * m_nSymSecParam);
|
||||
//m_lSendLock = new CLock;
|
||||
//InitAESKey(m_vKeySeeds, keybytes, m_nSymSecParam);
|
||||
};
|
||||
|
||||
|
||||
OTExtensionSender(uint32_t nSndVals, crypto* crypt, CSocket* sock, CBitVector& U, uint8_t* keybytes, uint32_t nbaseOTs) {
|
||||
Init(nSndVals, crypt, sock, U, keybytes, nbaseOTs);
|
||||
};
|
||||
|
||||
void Init(uint32_t nSndVals, crypto* crypt, CSocket* sock, CBitVector& U, uint8_t* keybytes, uint32_t nbaseOTs) {
|
||||
m_nSndVals = nSndVals;
|
||||
m_nSockets = sock;
|
||||
m_nU = U;
|
||||
m_nCounter = 0;
|
||||
m_cCrypto = crypt;
|
||||
m_nSymSecParam = m_cCrypto->get_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_ */
|
155
src/util/ot/xormasking.h
Normal file
155
src/util/ot/xormasking.h
Normal file
|
@ -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_ */
|
97
src/util/ot/xorrgbfmasking.h
Normal file
97
src/util/ot/xorrgbfmasking.h
Normal file
|
@ -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<limptr; outptr++, srcptr++, i++)
|
||||
{
|
||||
//if(m_vChoices.GetBitNoMask(i))
|
||||
if(GetBitRGBF(data, i))
|
||||
{
|
||||
memcpy(outptr[0], srcptr, m_nByteLength);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//output already has to contain the masks
|
||||
void UnMask(int progress, int processedOTs, CBitVector& choices, CBitVector& output, CBitVector& rcv_buf, CBitVector& tmpmask, BYTE protocol)
|
||||
{
|
||||
/* Do nothing*/
|
||||
};
|
||||
|
||||
void expandMask(CBitVector& out, BYTE* sbp, int offset, int processedOTs, int bitlength)
|
||||
{
|
||||
if(m_bID == RGBF_CLIENT)
|
||||
{
|
||||
//A hack write data into a fixed-size 2 dimensional out-bitvector for the GBF PSI protocl
|
||||
BYTE** outptr = ((BYTE**) (out.GetArr())) + offset;
|
||||
BYTE** limptr = outptr+processedOTs;
|
||||
BYTE* srcptr = sbp;
|
||||
BYTE* data = m_vChoices.GetArr();
|
||||
int bytelen = bitlength>>3;
|
||||
//for(int i = offset; i < offset+processedOTs; srcptr++, i++)
|
||||
for(int i = offset+m_nLeadingZeros; outptr<limptr; outptr++, srcptr++, i++)
|
||||
{
|
||||
if(GetBitRGBF(data, i))
|
||||
{
|
||||
//if(m_vChoices.GetBitNoMask(i))
|
||||
memcpy(outptr[0], srcptr, bytelen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(out.GetArr(), sbp, (bitlength * processedOTs)>>3);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t** m_vDelta;
|
||||
int m_nByteLength;
|
||||
uint8_t m_bID;
|
||||
CBitVector m_vChoices;
|
||||
int m_nLeadingZeros;
|
||||
};
|
||||
|
||||
#endif /* XORRGBFMASKING_H_ */
|
274
src/util/socket.h
Normal file
274
src/util/socket.h
Normal file
|
@ -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
|
||||
|
255
src/util/thread.h
Normal file
255
src/util/thread.h
Normal file
|
@ -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 <process.h>
|
||||
|
||||
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 <pthread.h>
|
||||
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
|
||||
|
||||
|
136
src/util/typedefs.h
Normal file
136
src/util/typedefs.h
Normal file
|
@ -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 <iostream>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
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 <WinSock2.h>
|
||||
#include <windows.h>
|
||||
|
||||
typedef unsigned short USHORT;
|
||||
typedef int socklen_t;
|
||||
#pragma comment(lib, "wsock32.lib")
|
||||
|
||||
#define SleepMiliSec(x) Sleep(x)
|
||||
|
||||
#else //WIN32
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
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<<targetlevel) < bits);
|
||||
}
|
||||
|
||||
static int floor_log2(int bits) {
|
||||
if(bits == 1) return 1;
|
||||
int targetlevel = 0;
|
||||
while (bits >>= 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_ */
|
Loading…
Reference in New Issue
Block a user