Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/cr-marcstevens/sha1collisiondetection.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Shumow <shumow@gmail.com>2017-03-03 08:58:01 +0300
committerDan Shumow <shumow@gmail.com>2017-03-03 08:58:01 +0300
commit7f0ab44fd057f109a9e6733be38571312d34fb1e (patch)
treeca2a26cb714e70ae1759bf252602f2830e7738fa
parent6b1c12f3606d0959f8658d44a324fcf5f4497f88 (diff)
Perf testing program for baseline analysis.
-rw-r--r--Makefile52
-rw-r--r--lib/sha1.h10
-rw-r--r--lib/ubc_check.h7
-rw-r--r--perf/main.cpp336
-rw-r--r--perf/random_hashing.cpp111
-rw-r--r--perf/test_util_lib.h16
6 files changed, 512 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index 9d62423..99c177f 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/lib/sha1.h b/lib/sha1.h
index 6f7d4d7..2ff9962 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -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);