diff options
author | Dan Shumow <shumow@gmail.com> | 2017-03-03 08:58:01 +0300 |
---|---|---|
committer | Dan Shumow <shumow@gmail.com> | 2017-03-03 08:58:01 +0300 |
commit | 7f0ab44fd057f109a9e6733be38571312d34fb1e (patch) | |
tree | ca2a26cb714e70ae1759bf252602f2830e7738fa | |
parent | 6b1c12f3606d0959f8658d44a324fcf5f4497f88 (diff) |
Perf testing program for baseline analysis.
-rw-r--r-- | Makefile | 52 | ||||
-rw-r--r-- | lib/sha1.h | 10 | ||||
-rw-r--r-- | lib/ubc_check.h | 7 | ||||
-rw-r--r-- | perf/main.cpp | 336 | ||||
-rw-r--r-- | perf/random_hashing.cpp | 111 | ||||
-rw-r--r-- | perf/test_util_lib.h | 16 |
6 files changed, 512 insertions, 20 deletions
@@ -11,6 +11,7 @@ TARGET ?= rpi2 endif TARGET ?= x86 CC ?= gcc +CPPC ?= g++ PREFIX ?= /usr/local BINDIR=$(PREFIX)/bin @@ -18,19 +19,27 @@ LIBDIR=$(PREFIX)/lib CFLAGS=-O2 -g -Wall -Werror -Wextra -pedantic -std=c99 -Ilib LDFLAGS=-O2 -g +CPPFLAGS=-O2 -g -Ilib LT_CC:=libtool --tag=CC --mode=compile $(CC) LT_CC_DEP:=$(CC) LT_LD:=libtool --tag=CC --mode=link $(CC) +LT_CPPC:=libtool --tag=CXX --mode=compile $(CPPC) +LT_CPPC_DEP:=$(CPPC) +LT_LD_CPPC:=libtool --tag=CXX --mode=link $(CPPC) + +BOOSTLIBS=/usr/lib/x86_64-linux-gnu/libboost_system.a /usr/lib/x86_64-linux-gnu/libboost_timer.a /usr/lib/x86_64-linux-gnu/libboost_program_options.a /usr/lib/x86_64-linux-gnu/libboost_timer.a /usr/lib/x86_64-linux-gnu/libboost_chrono.a + MKDIR=mkdir -p CC=${LT_CC} CC_DEP=${LT_CC_DEP} LD=${LT_LD} - - +CPPC=${LT_CPPC} +CPPC_DEP=${LT_CPPC_DEP} +LD_CPPC=${LT_LD_CPPC} HAVEMMX=0 HAVESSE=0 @@ -95,33 +104,27 @@ LIB_OBJ_DIR=obj_lib SRC_DIR=src SRC_DEP_DIR=dep_src SRC_OBJ_DIR=obj_src +PERF_DIR=perf +PERF_DEP_DIR=dep_perf +PERF_OBJ_DIR=obj_perf FS_LIB=$(filter-out $(wildcard ${LIB_DIR}/*_simd_*.c),$(wildcard ${LIB_DIR}/*.c)) FS_LIB+=$(FS_LIB_SIMD) FS_SRC=$(wildcard ${SRC_DIR}/*.c) +FS_PERF=${wildcard ${PERF_DIR}/*.cpp} FS_OBJ_LIB=$(FS_LIB:${LIB_DIR}/%.c=${LIB_OBJ_DIR}/%.lo) FS_OBJ_SRC=$(FS_SRC:${SRC_DIR}/%.c=${SRC_OBJ_DIR}/%.lo) -FS_OBJ=$(FS_OBJ_SRC) $(FS_OBJ_LIB) +FS_OBJ_PERF=$(FS_PERF:${PERF_DIR}/%.cpp=${PERF_OBJ_DIR}/%.lo) +FS_OBJ=$(FS_OBJ_SRC) $(FS_OBJ_LIB) $(FS_OBJ_PERF) FS_DEP_LIB=$(FS_LIB:${LIB_DIR}/%.c=${LIB_DEP_DIR}/%.d) FS_DEP_SRC=$(FS_SRC:${SRC_DIR}/%.c=${SRC_DEP_DIR}/%.d) -FS_DEP=$(FS_DEP_SRC) $(FS_DEP_LIB) +FS_DEP_PERF=$(FS_PERF:${PERF_DIR}/%.cpp=${PERF_DEP_DIR}/%.d) +FS_DEP=$(FS_DEP_SRC) $(FS_DEP_LIB) $(FS_DEP_PERF) -.SUFFIXES: .c .d +.SUFFIXES: .c .d .cpp .PHONY: all -all: library tools test - -.PHONY: install -install: all - install bin/sha1dcsum $(BINDIR) - install bin/sha1dcsum_partialcoll $(BINDIR) - install bin/libdetectcoll.la $(LIBDIR) - -.PHONY: uninstall -uninstall: - -$(RM) $(BINDIR)/sha1dcsum - -$(RM) $(BINDIR)/sha1dcsum_partialcoll - -$(RM) $(LIBDIR)/libdetectcoll.la +all: library tools test perf .PHONY: clean clean:: @@ -152,12 +155,17 @@ sha1dcsum_partialcoll: bin/sha1dcsum .PHONY: library library: bin/libdetectcoll.la +.PHONY: perf +perf: bin/perftest + bin/libdetectcoll.la: $(FS_OBJ_LIB) ${MKDIR} $(shell dirname $@) && ${LD} ${CFLAGS} $(FS_OBJ_LIB) -o bin/libdetectcoll.la bin/sha1dcsum: $(FS_OBJ_SRC) library ${LD} ${CFLAGS} $(FS_OBJ_SRC) $(FS_OBJ_LIB) -Lbin -ldetectcoll -o bin/sha1dcsum +bin/perftest: $(FS_OBJ_PERF) $(FS_OBJ_LIB) library + ${LD_CPPC} ${CPPFLAGS} $(FS_OBJ_PERF) $(FS_OBJ_LIB) $(BOOSTLIBS) -Lbin -ldetectcoll -o bin/perftest ${SRC_DEP_DIR}/%.d: ${SRC_DIR}/%.c ${MKDIR} $(shell dirname $@) && $(CC_DEP) $(CFLAGS) -M -MF $@ $< @@ -178,9 +186,12 @@ ${LIB_DEP_DIR}/%sse128.d: ${LIB_DIR}/%sse128.c ${LIB_DEP_DIR}/%avx256.d: ${LIB_DIR}/%avx256.c ${MKDIR} $(shell dirname $@) && $(CC_DEP) $(CFLAGS) $(AVXFLAGS) -M -MF $@ $< + ${LIB_DEP_DIR}/%neon128.d: ${LIB_DIR}/%neon128.c - ${MKDIR} $(shell dirname $@) && $(CC_DEP) $(CFLAGS) $(NEONFLAGS) -M -MF $@ $< + ${MKDIR} $(shell dirname $@) && $(CC_DEP) $(CFLAGS) $(NEONFLAGS) -M -MF $@ $< +${PERF_DEP_DIR}/%.d: ${PERF_DIR}/%.cpp + ${MKDIR} $(shell dirname $@) && $(CPPC_DEP) $(CPPFLAGS) -M -MF $@ $< ${LIB_OBJ_DIR}/%.lo ${LIB_OBJ_DIR}/%.o: ${LIB_DIR}/%.c ${LIB_DEP_DIR}/%.d @@ -198,5 +209,8 @@ ${LIB_OBJ_DIR}/%avx256.lo ${LIB_OBJ_DIR}/%avx256.o: ${LIB_DIR}/%avx256.c ${LIB_D ${LIB_OBJ_DIR}/%neon128.lo ${LIB_OBJ_DIR}/%neon128.o: ${LIB_DIR}/%neon128.c ${LIB_DEP_DIR}/%neon128.d ${MKDIR} $(shell dirname $@) && $(CC) $(CFLAGS) $(NEONFLAGS) -o $@ -c $< +${PERF_OBJ_DIR}/%.lo ${PERF_OBJ_DIR}/%.o: ${PERF_DIR}/%.cpp ${PERF_DEP_DIR}/%.d + ${MKDIR} $(shell dirname $@) && $(CPPC) $(CPPFLAGS) -o $@ -c $< + -include $(FS_DEP) @@ -5,6 +5,10 @@ * https://opensource.org/licenses/MIT ***/ +#if defined(__cplusplus) +extern "C" { +#endif + #include <stdint.h> // uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words @@ -91,4 +95,8 @@ void SHA1DCUpdate(SHA1_CTX*, const char*, unsigned); // obtain SHA-1 hash from SHA-1 context // returns: 0 = no collision detected, otherwise = collision found => warn user for active attack -int SHA1DCFinal(unsigned char[20], SHA1_CTX*); +int SHA1DCFinal(unsigned char[20], SHA1_CTX*); + +#if defined(__cplusplus) +} +#endif diff --git a/lib/ubc_check.h b/lib/ubc_check.h index 27285bd..52a5070 100644 --- a/lib/ubc_check.h +++ b/lib/ubc_check.h @@ -21,6 +21,10 @@ #ifndef UBC_CHECK_H #define UBC_CHECK_H +#if defined(__cplusplus) +extern "C" { +#endif + #include <stdint.h> #define DVMASKSIZE 1 @@ -31,5 +35,8 @@ void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]); #define DOSTORESTATE58 #define DOSTORESTATE65 +#if defined(__cplusplus) +} +#endif #endif // UBC_CHECK_H diff --git a/perf/main.cpp b/perf/main.cpp new file mode 100644 index 0000000..202f8c9 --- /dev/null +++ b/perf/main.cpp @@ -0,0 +1,336 @@ +#include <string.h> + +#include <iostream> +#include <vector> + +#include "sha1.h" + +#include "test_util_lib.h" + +#include <boost/tokenizer.hpp> +#include <boost/program_options.hpp> +#include <boost/timer/timer.hpp> + +namespace po = boost::program_options; + +using namespace std; + +#define UNUSED_PARAMETER(__X__) (void)(__X__) + +typedef struct _HashTimingRecord +{ + size_t cntBytes; + size_t cntIterations; + boost::timer::cpu_times timesHashing; + boost::timer::cpu_times timesOverhead; +} HashTimingRecord; + +void TimeHashing( + unsigned char *pb, + size_t cb, + size_t cntIterations, + boost::timer::cpu_times *pTimeElapsed, + bool fUBCCheck) +{ + SHA1_CTX ctx; + unsigned char hash[20]; + + boost::timer::cpu_timer t; + + unsigned char *pbLocal = pb; + + t.start(); + + for (size_t i = 0; i < cntIterations; i++) + { + SHA1DCInit(&ctx); + if (!fUBCCheck) + { + SHA1DCSetUseUBC(&ctx, 0); + } + SHA1DCUpdate(&ctx, (char*)pbLocal, cb); + SHA1DCFinal(hash, &ctx); + pbLocal += cb; + } + + t.stop(); + + *pTimeElapsed = t.elapsed(); + +} + +int EmptySHA1Update( + SHA1_CTX* ctx, + unsigned char* pb, + size_t cb) +{ + UNUSED_PARAMETER(ctx); + UNUSED_PARAMETER(pb); + UNUSED_PARAMETER(cb); + + return 0; +} + +int EmptySHA1Final( + unsigned char hash[20], + SHA1_CTX* ctx) +{ + UNUSED_PARAMETER(hash); + UNUSED_PARAMETER(ctx); + + return 0; +} + +void TimeLoopOverhead( + size_t cntIterations, + boost::timer::cpu_times *pTimeElapsed, + bool fUBCCheck) +{ + SHA1_CTX ctx; + unsigned char* pb = NULL; + size_t cb = 0; + unsigned char hash[20] = { 0 }; + + boost::timer::cpu_timer t; + + t.start(); + + for (size_t i = 0; i < cntIterations; i++) + { + SHA1DCInit(&ctx); + if (!fUBCCheck) + { + SHA1DCSetUseUBC(&ctx, 0); + } + EmptySHA1Update(&ctx, pb, cb); + EmptySHA1Final(hash, &ctx); + } + + t.stop(); + + *pTimeElapsed = t.elapsed(); +} + +void TimeNoDetectHashing( + unsigned char *pb, + size_t cb, + size_t cntIterations, + boost::timer::cpu_times *pTimeElapsed, + bool fUBCCheck) +{ + SHA1_CTX ctx; + unsigned char hash[20]; + + boost::timer::cpu_timer t; + + unsigned char *pbLocal = pb; + + t.start(); + + for (size_t i = 0; i < cntIterations; i++) + { + SHA1DCInit(&ctx); + SHA1DCSetUseDetectColl(&ctx, 0); + SHA1DCUpdate(&ctx, (char*)pbLocal, cb); + SHA1DCFinal(hash, &ctx); + pbLocal += cb; + } + + t.stop(); + + *pTimeElapsed = t.elapsed(); + +} + +int GenRandomAndPerformHashTimings( + size_t cntBytes, + size_t cntIterations, + br::mt19937 rng, + HashTimingRecord *pHashTimingRecord, + bool fUBCCheck) +{ + unsigned char* pb = NULL; + + int ret = -1; + + pb = (unsigned char*)malloc(cntBytes*cntIterations); + if (NULL == pb) + { + ret = -1; + goto Cleanup; + } + + pHashTimingRecord->cntBytes = cntBytes; + pHashTimingRecord->cntIterations = cntIterations; + + GenRandomBytes(pb, cntBytes*cntIterations, rng); + + cout << "Hashing " << cntBytes << " bytes of data in " << cntIterations << " iterations " << endl; + TimeHashing(pb, cntBytes, cntIterations, &pHashTimingRecord->timesHashing, fUBCCheck); + cout << "Loop Overhead of " << cntIterations << "iterations" << endl; + TimeLoopOverhead(cntIterations, &pHashTimingRecord->timesOverhead, fUBCCheck); + + ret = 0; + +Cleanup: + + if (pb) + { + free(pb); + } + + return ret; + +} + +int GenRandomAndPerformHashTimings_NoDetect( + size_t cntBytes, + size_t cntIterations, + br::mt19937 rng, + HashTimingRecord *pHashTimingRecord, + bool fUBCCheck) +{ + unsigned char* pb = NULL; + + int ret = -1; + + pb = (unsigned char*)malloc(cntBytes*cntIterations); + if (NULL == pb) + { + ret = -1; + goto Cleanup; + } + + pHashTimingRecord->cntBytes = cntBytes; + pHashTimingRecord->cntIterations = cntIterations; + + GenRandomBytes(pb, cntBytes*cntIterations, rng); + + cout << "Hashing " << cntBytes << " bytes of data in " << cntIterations << " iterations " << endl; + TimeNoDetectHashing(pb, cntBytes, cntIterations, &pHashTimingRecord->timesHashing, fUBCCheck); + cout << "Loop Overhead of " << cntIterations << "iterations" << endl; + TimeLoopOverhead(cntIterations, &pHashTimingRecord->timesOverhead, fUBCCheck); + + ret = 0; + +Cleanup: + + if (pb) + { + free(pb); + } + + return ret; + +} + +int main(int argc, char** argv) +{ + unsigned int uiSeed; + + string strCounts; + string strSeed; + + boost::char_separator<char> sep(",;"); + + int ret = -1; + + bool fUBCCheck = false; + + po::options_description desc("Allowed options"); + + desc.add_options() + ("help,h", "Show options") + ("counts,c", po::value<string>(&strCounts)->default_value("32,64,128,256"), "Count of bytes to hash.") + ("seed,s", po::value<string>(&strSeed), "Seed to use for rand.") + ("UBC,u", "Enable Unavoidable Bit Condition checks."); + po::variables_map vm; + po::store(po::command_line_parser(argc, argv).options(desc).run(), vm); + po::notify(vm); + + boost::tokenizer<boost::char_separator<char> > tokens(strCounts, sep); + boost::tokenizer<boost::char_separator<char> >::iterator cur_token; + + br::mt19937 rng; + + vector<HashTimingRecord> records; + vector<HashTimingRecord> records_no_detect; + + HashTimingRecord *phash_timing_record = NULL; + HashTimingRecord *phash_timing_record_no_detect = NULL; + + if (0 < vm.count("help")) + { + cout << desc << endl; + ret = 0; + goto Cleanup; + } + + if (0 < vm.count("seed")) + { + + uiSeed = atoi(strSeed.c_str()); + cout << "Using specified seed: " << uiSeed << "." << endl; + } + else + { + uiSeed = (unsigned int)time(NULL); + cout << "No random seed specified, using time(Null):" << uiSeed << "." << endl; + } + + if (0 < vm.count("UBC")) + { + fUBCCheck = true; + cout << "Performing unavoidable bit condition checks." << endl; + } + + rng = br::mt19937(uiSeed); + + phash_timing_record = (HashTimingRecord*)malloc(sizeof(HashTimingRecord)); + phash_timing_record_no_detect = (HashTimingRecord*)malloc(sizeof(HashTimingRecord)); + + for (cur_token = tokens.begin(); cur_token != tokens.end(); ++cur_token) + { + size_t cntBytes = (size_t)atoi(cur_token.current_token().c_str()); + size_t cntIterations = (size_t)ceil((double)(1 << 24) / cntBytes); + cout << "Performing timing for: <" << cntBytes << "> "; + + GenRandomAndPerformHashTimings(cntBytes, cntIterations, rng, phash_timing_record, fUBCCheck); + GenRandomAndPerformHashTimings_NoDetect(cntBytes, cntIterations, rng, phash_timing_record_no_detect, fUBCCheck); + + records.push_back(*phash_timing_record); + records_no_detect.push_back(*phash_timing_record_no_detect); + } + cout << endl; + + // top of columns + printf("bytes\titerations\thashing wall\thashing user\thashing system\thashing total\toverhead wall\toverhead user\toverhead system\toverhead total\n"); + + for (vector<HashTimingRecord>::iterator rec = records.begin(); rec != records.end(); rec++) + { + printf("%lu\t%lu\t\t", rec->cntBytes, rec->cntIterations); + printf("%li\t%li\t%li\t\t%li\t", rec->timesHashing.wall, rec->timesHashing.user, rec->timesHashing.system, (rec->timesHashing.user + rec->timesHashing.system)); + printf("%li\t\t%li\t\t%li\t\t%li\n", rec->timesOverhead.wall, rec->timesOverhead.user, rec->timesOverhead.system, (rec->timesOverhead.user + rec->timesOverhead.system)); + } + + // top of columns + printf("bytes\titerations\thashing wall\thashing user\thashing system\thashing total\toverhead wall\toverhead user\toverhead system\toverhead total\n"); + + for (vector<HashTimingRecord>::iterator rec = records_no_detect.begin(); rec != records_no_detect.end(); rec++) + { + printf("%lu\t%lu\t\t", rec->cntBytes, rec->cntIterations); + printf("%li\t%li\t%li\t\t%li\t", rec->timesHashing.wall, rec->timesHashing.user, rec->timesHashing.system, (rec->timesHashing.user + rec->timesHashing.system)); + printf("%li\t\t%li\t\t%li\t\t%li\n", rec->timesOverhead.wall, rec->timesOverhead.user, rec->timesOverhead.system, (rec->timesOverhead.user + rec->timesOverhead.system)); + } + + ret = 0; + +Cleanup: + + if (phash_timing_record) + { + free(phash_timing_record); + } + + return ret; +} diff --git a/perf/random_hashing.cpp b/perf/random_hashing.cpp new file mode 100644 index 0000000..fc85204 --- /dev/null +++ b/perf/random_hashing.cpp @@ -0,0 +1,111 @@ +#include <string.h>
+#include <stdio.h> +#include <algorithm>
+
+#include <iostream>
+
+#include "sha1.h"
+#include "ubc_check.h"
+ +#include "test_util_lib.h"
+
+using namespace std;
+
+int GenRandomBytes(
+ unsigned char* pb,
+ size_t cb,
+ br::mt19937 &rng)
+{
+ size_t i;
+
+ for (i = 0; i < cb; i++)
+ {
+ pb[i] = (unsigned char)rng();
+ }
+
+ return i;
+
+}
+
+int HashRandomBytes(
+ size_t cntBytesToHash,
+ unsigned int uiSeed)
+{
+ unsigned char hash[20];
+
+ unsigned char buffer_to_hash[64];
+
+ SHA1_CTX ctx;
+
+ int i = cntBytesToHash;
+
+ br::mt19937 rng(uiSeed);
+ cout << "Hashing...";
+ SHA1DCInit(&ctx);
+
+ while (0 < i)
+ {
+ unsigned int cb = min(64, i);
+
+ cb = GenRandomBytes(buffer_to_hash, cb, rng);
+
+ SHA1DCUpdate(&ctx, (char *)buffer_to_hash, cb);
+
+ i -= cb;
+ }
+
+ SHA1DCFinal(hash, &ctx);
+
+ cout << "Done." << endl;
+
+ if (ctx.found_collision)
+ {
+ cout << "Collision found." << endl;
+ }
+
+ return 0;
+
+}
+
+int UBCVerifyRandomBytes(
+ size_t cntBytesToHash,
+ unsigned int uiSeed)
+{
+ unsigned char buffer_to_hash[64];
+
+ uint32_t expanded_message[80];
+
+ uint32_t dvmask[1] = { 0 };
+ uint32_t dvmask_verify[1] = { 0 };
+
+ int i = cntBytesToHash;
+
+ br::mt19937 rng(uiSeed);
+ cout << "Unavoidable bit checking...";
+
+ while (0 < i)
+ {
+ unsigned int cb = min(64, i);
+
+ cb = GenRandomBytes(buffer_to_hash, cb, rng);
+
+ memset(dvmask, 0, sizeof(dvmask));
+ memset(dvmask_verify, 0, sizeof(dvmask_verify));
+
+ sha1_compression_W((uint32_t*)buffer_to_hash, expanded_message);
+
+ ubc_check(expanded_message, dvmask);
+ //ubc_check_verify(expanded_message, dvmask_verify);
+
+ if (0 != memcmp(dvmask, dvmask_verify, sizeof(dvmask)))
+ {
+ printf("Calculated dvmask does not equal dvmask verify output.\n");
+ }
+
+ i -= cb;
+ }
+
+ cout << "Done." << endl;
+
+ return 0;
+}
diff --git a/perf/test_util_lib.h b/perf/test_util_lib.h new file mode 100644 index 0000000..4a66b5c --- /dev/null +++ b/perf/test_util_lib.h @@ -0,0 +1,16 @@ +#include <boost/random/mersenne_twister.hpp>
+
+namespace br = boost::random;
+
+int GenRandomBytes(
+ unsigned char* pb,
+ size_t cb,
+ br::mt19937 &rng);
+
+int HashRandomBytes(
+ size_t cntBytesToHash,
+ unsigned int uiSeed);
+
+int UBCVerifyRandomBytes(
+ size_t cntBytesToHash,
+ unsigned int uiSeed);
|