Initial file upload

This commit is contained in:
Michael Zohner 2015-05-15 11:03:23 +02:00
parent 2ff1fb7e17
commit 0864e04217
51 changed files with 9800 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "src/externals/Miracl"]
path = src/externals/Miracl
url = git://github.com/CertiVox/Miracl.git

52
Makefile Normal file
View 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
View 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
View 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
View 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

@ -0,0 +1 @@
Subproject commit cff161bad6364548b361b63938a988db23f60c2a

196
src/hashing/cuckoo.cpp Normal file
View 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
View 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
View 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
View 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
View 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 );
}

View 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);
}

View 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
View 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

View 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);
}

View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

55
src/thirdparty/shpsi.h vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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_ */

View 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);
}

View 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, (&params))
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_ */

View 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);
}
}

View 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_ */

View 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

Binary file not shown.

53
src/util/ot/baseOT.h Normal file
View 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_ */

View 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
View 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
View 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
View 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 */

View 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;
}

View 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

View 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
View 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
View 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 = &delta; 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_ */

View 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
View 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
View 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
View 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_ */