aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuraj Somorovsky <[email protected]>2016-11-19 23:42:21 +0100
committerJuraj Somorovsky <[email protected]>2016-11-20 00:17:03 +0100
commit5848645d0726157a0a1ba8c811dc3d3567fc500e (patch)
treefe43ebc53ae8177aa63d180435f7801658ddc53c
parent1e21b64bb96815ebadfab892a73094c758db142d (diff)
Timing test suite with the mona timing library
-rw-r--r--src/extra_tests/timing/README.md15
-rwxr-xr-xsrc/extra_tests/timing/setup.sh22
-rwxr-xr-xsrc/extra_tests/timing/testsuite.sh23
-rw-r--r--src/extra_tests/timing/timing-tests/BleichenbacherTest.cpp36
-rw-r--r--src/extra_tests/timing/timing-tests/Lucky13Test.cpp55
-rw-r--r--src/extra_tests/timing/timing-tests/Makefile25
-rw-r--r--src/extra_tests/timing/timing-tests/MangerTest.cpp41
-rw-r--r--src/extra_tests/timing/timing-tests/TimingTest.cpp82
-rw-r--r--src/extra_tests/timing/timing-tests/TimingTest.h102
-rw-r--r--src/extra_tests/timing/timing-tests/data/bleichenbacher.vec8
-rw-r--r--src/extra_tests/timing/timing-tests/data/lucky13sec3.vec4
-rw-r--r--src/extra_tests/timing/timing-tests/data/lucky13sec4sha1.vec13
-rw-r--r--src/extra_tests/timing/timing-tests/data/lucky13sec4sha256.vec7
-rw-r--r--src/extra_tests/timing/timing-tests/data/lucky13sha384.vec11
-rw-r--r--src/extra_tests/timing/timing-tests/data/manger.vec4
-rw-r--r--src/extra_tests/timing/timing-tests/main.cpp141
16 files changed, 589 insertions, 0 deletions
diff --git a/src/extra_tests/timing/README.md b/src/extra_tests/timing/README.md
new file mode 100644
index 000000000..98fde428c
--- /dev/null
+++ b/src/extra_tests/timing/README.md
@@ -0,0 +1,15 @@
+# Timing testsuite
+
+Extended Botan library test suite with mona-timing-lib.
+
+Run
+```bash
+setup.sh
+```
+to download and build the recent mona-timing-lib version.
+
+Run
+```bash
+testsuite.sh
+```
+to start the test suite. \ No newline at end of file
diff --git a/src/extra_tests/timing/setup.sh b/src/extra_tests/timing/setup.sh
new file mode 100755
index 000000000..4e2c52fb0
--- /dev/null
+++ b/src/extra_tests/timing/setup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+mkdir timing-tests/results
+mkdir timing-tests/results/bleichenbacher
+mkdir timing-tests/results/lucky13sec3
+mkdir timing-tests/results/lucky13sec4
+mkdir timing-tests/results/lucky13sha256sec3
+mkdir timing-tests/results/lucky13sha256sec4
+mkdir timing-tests/results/lucky13sha384
+mkdir timing-tests/results/manger
+
+if [ ! -d mona-timing-report ]
+then
+ git clone https://github.com/seecurity/mona-timing-report.git
+fi
+
+cd mona-timing-report
+ant
+
+cd ../../../../
+./configure.py
+make -j4
diff --git a/src/extra_tests/timing/testsuite.sh b/src/extra_tests/timing/testsuite.sh
new file mode 100755
index 000000000..186624c46
--- /dev/null
+++ b/src/extra_tests/timing/testsuite.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+cd timing-tests
+make
+./main
+
+zipdate=$(date +%d-%H-%M)
+zipfile="${zipdate}-results.zip"
+zip -r $zipfile results
+
+cd ..
+cd mona-timing-report
+
+for dir in ../timing-tests/results/*;
+do
+ echo "Working in directory: " $dir
+ for file in $dir/*;
+ do
+ echo "Creating report for: " $file
+ java -jar ReportingTool.jar --inputFile=$file --name=$file --lowerBound=0.4 --upperBound=0.5
+ rm $file
+ done
+done
diff --git a/src/extra_tests/timing/timing-tests/BleichenbacherTest.cpp b/src/extra_tests/timing/timing-tests/BleichenbacherTest.cpp
new file mode 100644
index 000000000..abef8a7be
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/BleichenbacherTest.cpp
@@ -0,0 +1,36 @@
+/*
+ * File: BleichenbacherTest.cpp
+ * Author: Juraj Somorovsky - [email protected]
+ *
+ */
+
+#include "TimingTest.h"
+
+BleichenbacherTest::BleichenbacherTest(std::vector<std::string> &inputs,
+ std::string result_folder, int keysize) :
+ m_privkey(system_rng(), keysize),
+ m_pubkey(m_privkey),
+ m_enc(m_pubkey, m_encrypt_padding),
+ m_dec(m_privkey, m_decrypt_padding)
+ {
+ m_inputs = inputs;
+ m_result_folder = result_folder;
+ }
+
+std::vector<byte> BleichenbacherTest::prepare_input(std::string input)
+ {
+ const std::vector<uint8_t> input_vector = Botan::hex_decode(input);
+ const std::vector<byte> encrypted = m_enc.encrypt(input_vector, system_rng());
+ return encrypted;
+ }
+
+ticks BleichenbacherTest::measure_critical_function(std::vector<byte> input)
+ {
+ const Botan::byte* in = &input[0];
+
+ ticks start = this->get_ticks();
+ m_dec.decrypt_or_random(in, m_ctext_length, m_expected_content_size, system_rng());
+ ticks end = get_ticks();
+
+ return (end - start);
+ }
diff --git a/src/extra_tests/timing/timing-tests/Lucky13Test.cpp b/src/extra_tests/timing/timing-tests/Lucky13Test.cpp
new file mode 100644
index 000000000..55f7dab1b
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/Lucky13Test.cpp
@@ -0,0 +1,55 @@
+/*
+ * File: Lucky13Test.cpp
+ * Author: Juraj Somorovsky - [email protected]
+ *
+ */
+
+#include "TimingTest.h"
+
+Lucky13Test::Lucky13Test(std::vector<std::string> &inputs, std::string result_folder,
+ const std::string& mac_name, size_t mac_keylen) :
+ m_dec("AES-128", 16, mac_name, mac_keylen, true, false),
+ m_mac_keylen (mac_keylen)
+ {
+ m_inputs = inputs;
+ m_result_folder = result_folder;
+ }
+
+std::vector<byte> Lucky13Test::prepare_input(std::string input)
+ {
+ const std::vector<uint8_t> input_vector = Botan::hex_decode(input);
+ const std::vector<uint8_t> key(16);
+ const std::vector<uint8_t> iv(16);
+
+ std::unique_ptr<Botan::Cipher_Mode> enc(Botan::get_cipher_mode("AES-128/CBC/NoPadding", Botan::ENCRYPTION));
+ enc->set_key(key);
+ enc->start(iv);
+ Botan::secure_vector<uint8_t> buf(input_vector.begin(), input_vector.end());
+ enc->finish(buf);
+
+ return unlock(buf);
+ }
+
+ticks Lucky13Test::measure_critical_function(std::vector<byte> input)
+ {
+ Botan::secure_vector<byte> data(input.begin(), input.end());
+ Botan::secure_vector<byte> aad(13);
+ const Botan::secure_vector<byte> iv(16);
+ Botan::secure_vector<byte> key(16 + m_mac_keylen);
+
+ m_dec.set_key(unlock(key));
+ m_dec.set_ad(unlock(aad));
+ m_dec.start(unlock(iv));
+
+ ticks start = this->get_ticks();
+ try
+ {
+ m_dec.finish(data);
+ }
+ catch (Botan::TLS::TLS_Exception e)
+ {
+
+ }
+ ticks end = get_ticks();
+ return (end - start);
+ }
diff --git a/src/extra_tests/timing/timing-tests/Makefile b/src/extra_tests/timing/timing-tests/Makefile
new file mode 100644
index 000000000..5497da9bb
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/Makefile
@@ -0,0 +1,25 @@
+CC=g++
+BOTAN_DIR=../../../../../botan/
+LDIR=$(BOTAN_DIR)
+IDIR=$(BOTAN_DIR)build/include
+DBG_FLAGS=-g -O3
+LIBS=-lbotan-1.11
+
+CPPFLAGS=$(DBG_FLAGS) -std=c++11 -I$(IDIR) -L$(LDIR) -Wl,-R$(LDIR) '-Wl,-R$$ORIGIN'
+LDFLAGS=$(DBG_FLAGS) -I$(IDIR) -L$(LDIR) -Wl,-R$(LDIR) '-Wl,-R$$ORIGIN' $(LIBS)
+
+SOURCES = $(shell find . -maxdepth 1 -name "*.cpp")
+HEADERS = $(shell find . -maxdepth 1 -name "*.h")
+OBJECTS = $(SOURCES:%.cpp=%.o)
+BINARY = main
+
+all: ${BINARY}
+
+${BINARY}: $(OBJECTS) $(HEADERS)
+ ${CC} $(LDFLAGS) -o ${BINARY} $(OBJECTS) $(LIBS)
+
+# rebuild objects if headers changed
+$(OBJECTS): $(HEADERS)
+
+clean:
+ rm -f ${BINARY} $(OBJECTS)
diff --git a/src/extra_tests/timing/timing-tests/MangerTest.cpp b/src/extra_tests/timing/timing-tests/MangerTest.cpp
new file mode 100644
index 000000000..6ed39819b
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/MangerTest.cpp
@@ -0,0 +1,41 @@
+/*
+ * File: MangerTest.cpp
+ * Author: Juraj Somorovsky - [email protected]
+ *
+ */
+
+#include "TimingTest.h"
+
+MangerTest::MangerTest(std::vector<std::string> &inputs, std::string result_folder, int keysize) :
+ m_privkey(system_rng(), keysize),
+ m_pubkey(m_privkey),
+ m_enc(m_pubkey, m_encrypt_padding),
+ m_dec(m_privkey, m_decrypt_padding)
+ {
+ m_inputs = inputs;
+ m_result_folder = result_folder;
+ }
+
+std::vector<byte> MangerTest::prepare_input(std::string input)
+ {
+ const std::vector<uint8_t> input_vector = Botan::hex_decode(input);
+ const std::vector<byte> encrypted = m_enc.encrypt(input_vector, system_rng());
+ return encrypted;
+ }
+
+ticks MangerTest::measure_critical_function(std::vector<byte> input)
+ {
+ const Botan::byte* in = &input[0];
+
+ ticks start = this->get_ticks();
+ try
+ {
+ m_dec.decrypt(in, m_ctext_length);
+ }
+ catch (Botan::Decoding_Error e)
+ {
+ }
+ ticks end = get_ticks();
+
+ return (end - start);
+ }
diff --git a/src/extra_tests/timing/timing-tests/TimingTest.cpp b/src/extra_tests/timing/timing-tests/TimingTest.cpp
new file mode 100644
index 000000000..f33cbd34e
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/TimingTest.cpp
@@ -0,0 +1,82 @@
+/*
+ * File: TimingTest.cpp
+ * Author: Juraj Somorovsky - [email protected]
+ *
+ */
+
+#include "TimingTest.h"
+#include <time.h>
+
+TimingTest::TimingTest()
+ {
+ }
+
+TimingTest::~TimingTest()
+ {
+ }
+
+void TimingTest::execute_evaluation()
+ {
+ m_results = std::vector<ticks>(m_measurement_iterations * 2);
+
+ for (int i = 0; i < m_inputs.size() - 1; i++)
+ {
+ for (int j = i + 1; j < m_inputs.size(); j++)
+ {
+ std::cout << "\nExecuting measurements for inputs " << i << " and " << j;
+ std::vector<byte> input1 = prepare_input(m_inputs[i]);
+ std::vector<byte> input2 = prepare_input(m_inputs[j]);
+
+ for (int k = 0; k < m_warmup_iterations + m_measurement_iterations; k++)
+ {
+ ticks t1 = measure_critical_function(input1);
+ ticks t2 = measure_critical_function(input2);
+
+ if (k >= m_warmup_iterations)
+ {
+ m_results[ (k - m_warmup_iterations) * 2] = t1;
+ m_results[ (k - m_warmup_iterations) * 2 + 1] = t2;
+ }
+ }
+ clock_t t;
+ t = clock();
+ store_results_in_file(std::to_string(t) + "test" + std::to_string(i) + std::to_string(j));
+ }
+ }
+ }
+
+void TimingTest::store_results_in_file(std::string file)
+ {
+ std::ofstream output(m_result_folder + "/" + file);
+ for (int i = 0; i < m_measurement_iterations; i++)
+ {
+ output << 2 * i << ";1;" << m_results[2 * i] << "\n";
+ output << 2 * i + 1 << ";2;" << m_results[2 * i + 1] << "\n";
+ }
+ }
+
+/**
+ * Taken from Mona Timing Lib
+ * Thanks Sebastian ;)
+ *
+ * @return Number of processor ticks read using the RDTSC assembler instruction.
+ */
+ticks TimingTest::get_ticks()
+ {
+ ticks ret = 0;
+ unsigned long minor = 0;
+ unsigned long mayor = 0;
+
+ asm volatile(
+ "cpuid \n"
+ "rdtsc"
+ : "=a"(minor),
+ "=d"(mayor)
+ : "a" (0)
+ : "%ebx", "%ecx"
+ );
+
+ ret = ((((ticks) mayor) << 32) | ((ticks) minor));
+
+ return ret;
+ }
diff --git a/src/extra_tests/timing/timing-tests/TimingTest.h b/src/extra_tests/timing/timing-tests/TimingTest.h
new file mode 100644
index 000000000..a61e21519
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/TimingTest.h
@@ -0,0 +1,102 @@
+/*
+ * File: TimingTest.h
+ * Author: Juraj Somorovsky - [email protected]
+ *
+ */
+
+#ifndef TIMINGTEST_H
+#define TIMINGTEST_H
+
+#include <botan/pubkey.h>
+#include <botan/rsa.h>
+#include <botan/system_rng.h>
+#include <botan/hex.h>
+#include <botan/rng.h>
+#include <botan/numthry.h>
+#include <iostream>
+#include <vector>
+#include <fstream>
+#include <botan/internal/tls_cbc.h>
+#include <botan/tls_exceptn.h>
+#include <botan/cipher_mode.h>
+
+using namespace Botan;
+
+typedef unsigned long long ticks;
+
+class TimingTest
+ {
+ protected:
+ std::string m_result_folder;
+ std::vector<std::string> m_inputs;
+ std::vector<ticks> m_results;
+ unsigned int m_warmup_iterations = 500;
+ unsigned int m_measurement_iterations = 10000;
+ virtual std::vector<byte> prepare_input(std::string input) = 0;
+ virtual ticks measure_critical_function(std::vector<byte> input) = 0;
+
+ public:
+ TimingTest();
+ virtual ~TimingTest();
+ void execute_evaluation();
+ void store_results_in_file(std::string file_name);
+ ticks get_ticks();
+ };
+
+class BleichenbacherTest : public TimingTest
+ {
+ private:
+ const std::string m_encrypt_padding = "Raw";
+ const std::string m_decrypt_padding = "PKCS1v15";
+ const size_t m_expected_content_size = 48;
+ const size_t m_ctext_length = 256;
+ RSA_PrivateKey m_privkey;
+ RSA_PublicKey m_pubkey;
+ PK_Encryptor_EME m_enc;
+ PK_Decryptor_EME m_dec;
+
+ protected:
+ std::vector<byte> prepare_input(std::string input) override;
+ ticks measure_critical_function(std::vector<byte> input) override;
+
+ public:
+ BleichenbacherTest(std::vector<std::string> &inputs, std::string result_file, int keysize);
+ };
+
+class MangerTest : public TimingTest
+ {
+ private:
+ const std::string m_encrypt_padding = "Raw";
+ const std::string m_decrypt_padding = "EME1(SHA-256)";
+ const size_t m_ctext_length = 256;
+ RSA_PrivateKey m_privkey;
+ RSA_PublicKey m_pubkey;
+ PK_Encryptor_EME m_enc;
+ PK_Decryptor_EME m_dec;
+
+ protected:
+ std::vector<byte> prepare_input(std::string input) override;
+ ticks measure_critical_function(std::vector<byte> input) override;
+
+ public:
+ MangerTest(std::vector<std::string> &inputs, std::string result_file, int keysize);
+ };
+
+class Lucky13Test : public TimingTest
+ {
+ private:
+ const std::string m_mac_algo;
+ const size_t m_mac_keylen;
+ Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption m_dec;
+
+ protected:
+ std::vector<byte> prepare_input(std::string input) override;
+ ticks measure_critical_function(std::vector<byte> input) override;
+
+ public:
+ Lucky13Test(std::vector<std::string> &inputs, std::string result_file,
+ const std::string& mac_name, size_t mac_keylen);
+ };
+
+
+#endif /* TIMINGTEST_H */ \ No newline at end of file
diff --git a/src/extra_tests/timing/timing-tests/data/bleichenbacher.vec b/src/extra_tests/timing/timing-tests/data/bleichenbacher.vec
new file mode 100644
index 000000000..76df90e68
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/data/bleichenbacher.vec
@@ -0,0 +1,8 @@
+# valid padding
+00021F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F00F1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1
+# invalid padding
+00031F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F00F1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1
+# no zero
+00021F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1FF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1
+# invalid length
+00021F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F001F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1FF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1 \ No newline at end of file
diff --git a/src/extra_tests/timing/timing-tests/data/lucky13sec3.vec b/src/extra_tests/timing/timing-tests/data/lucky13sec3.vec
new file mode 100644
index 000000000..97b7548bc
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/data/lucky13sec3.vec
@@ -0,0 +1,4 @@
+# Lucky 13 Section 3 - Distinguishing attack: 32 bytes of data followed by maximum padding 0xFF, 18 plaintext blocks
+00000000000000000000000000000000 00000000000000000000000000000000 ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff
+# Lucky 13 Section 3 - Distinguishing attack: minimum padding 0x00, 18 plaintext blocks
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000
diff --git a/src/extra_tests/timing/timing-tests/data/lucky13sec4sha1.vec b/src/extra_tests/timing/timing-tests/data/lucky13sec4sha1.vec
new file mode 100644
index 000000000..ee11ec5db
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/data/lucky13sec4sha1.vec
@@ -0,0 +1,13 @@
+# Lucky 13 Section 4.2: 4 plaintext blocks
+# Case 0: 0x00 padding byte
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000
+# Case 1: At least two valid padding bytes
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000101
+# Case 2: Invalid padding
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000004030303
+# Further cases (only for extended validations)
+#00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000020202
+#00000000000000000000000000000000 00000000000000000000000000000000 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F
+#00000000000000000000000000000000 00000000000000000000000000000000
+#00000000000000000000000000000000 00000000000000000000000000000101
+#00000000000000000000000000000000 00000000000000000000000004030303 \ No newline at end of file
diff --git a/src/extra_tests/timing/timing-tests/data/lucky13sec4sha256.vec b/src/extra_tests/timing/timing-tests/data/lucky13sec4sha256.vec
new file mode 100644
index 000000000..d542238f6
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/data/lucky13sec4sha256.vec
@@ -0,0 +1,7 @@
+# Lucky 13 Section 4.2: 5 plaintext blocks, now for sha256. 32 bytes of output
+# Case 0: 0x00 padding byte
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000
+# Case 1: At least six valid padding bytes: 80+13-32-7 = 56
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000006060606060606
+# Case 2: Invalid padding
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000004030303
diff --git a/src/extra_tests/timing/timing-tests/data/lucky13sha384.vec b/src/extra_tests/timing/timing-tests/data/lucky13sha384.vec
new file mode 100644
index 000000000..b5a0e2441
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/data/lucky13sha384.vec
@@ -0,0 +1,11 @@
+# Lucky 13 test for SHA-384 (48 bytes output). SHA-384 uses 128 byte block length and 16 byte long encoding
+# <= 111 bytes: 1 compression
+# (111, 239] bytes: 2 compressions ...
+# Case 0: 160 bytes, 0x00 padding byte, results in (160-1-48+13)=124 MACed bytes
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000
+# Case 1: 160 bytes, 0x0D padding byte, results in (160-14-48+13)=111 MACed bytes
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D
+# Case 2: Further case with invalid padding
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 0000000000000000000000000000000A
+# Case 3: Further case with 0x0C
+00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C \ No newline at end of file
diff --git a/src/extra_tests/timing/timing-tests/data/manger.vec b/src/extra_tests/timing/timing-tests/data/manger.vec
new file mode 100644
index 000000000..1c370e0e5
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/data/manger.vec
@@ -0,0 +1,4 @@
+# valid first padding byte
+00021F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F00F1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1
+# invalid first padding byte
+01021F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F00F1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1F1FFF1F1F1F1F1F1F1F1 \ No newline at end of file
diff --git a/src/extra_tests/timing/timing-tests/main.cpp b/src/extra_tests/timing/timing-tests/main.cpp
new file mode 100644
index 000000000..7b9e2b0fc
--- /dev/null
+++ b/src/extra_tests/timing/timing-tests/main.cpp
@@ -0,0 +1,141 @@
+/*
+ * File: main.cpp
+ * Author: Juraj Somorovsky - [email protected]
+ *
+ */
+
+#include <botan/pubkey.h>
+#include <botan/rsa.h>
+#include <botan/system_rng.h>
+#include <botan/hex.h>
+#include <botan/rng.h>
+#include <iostream>
+#include <vector>
+#include <fstream>
+#include <sstream>
+#include <dirent.h>
+#include <botan/numthry.h>
+
+
+#include "TimingTest.h"
+
+/**
+ * Reads directory and outputs a vector of files.
+ *
+ * @param dir_path
+ * @return
+ */
+std::vector<std::string> read_dir(const std::string& dir_path)
+ {
+ DIR *dir;
+ struct dirent *ent;
+ std::vector<std::string> out;
+ if ((dir = opendir(dir_path.c_str())) != NULL)
+ {
+ while ((ent = readdir(dir)) != NULL)
+ {
+ const std::string filename = ent->d_name;
+ if (filename == "." || filename == "..")
+ {
+ continue;
+ }
+ const std::string full_path = dir_path + "/" + filename;
+ out.push_back(full_path);
+ }
+ closedir(dir);
+ }
+ return out;
+ }
+
+/*
+ * Reads vectors from a given file
+ *
+ */
+std::vector<std::string> read_vectors(const std::string& filename)
+ {
+ std::string line;
+ std::ifstream infile(filename);
+ std::vector<std::string> out;
+ while (std::getline(infile, line))
+ {
+ if (line.at(0) != '#')
+ {
+ out.push_back(line);
+ }
+ }
+ return out;
+ }
+
+bool executeEvaluationWithFile(std::string test, std::string filename, std::string arg)
+ {
+ if ((arg == "" || test.find(arg) != std::string::npos) &&
+ (filename.find(test) != std::string::npos))
+ {
+ return true;
+ }
+ return false;
+ }
+
+int main(int argc, char* argv[])
+ {
+ std::vector<std::string> files = read_dir("data");
+ std::string test_arg;
+ if(argc < 2)
+ {
+ test_arg = "";
+ }
+ else
+ {
+ test_arg = argv[1];
+ }
+ for (auto const& file : files)
+ {
+ std::vector<std::string> inputs = read_vectors(file);
+
+ if (executeEvaluationWithFile("bleichenbacher", file, test_arg))
+ {
+ std::string result_folder = "results/bleichenbacher";
+ std::unique_ptr<BleichenbacherTest> test(new BleichenbacherTest(inputs, result_folder, 2048));
+ test->execute_evaluation();
+ }
+ else if (executeEvaluationWithFile("manger", file, test_arg))
+ {
+ std::string result_folder = "results/manger";
+ std::unique_ptr<MangerTest> test(new MangerTest(inputs, result_folder, 2048));
+ test->execute_evaluation();
+ }
+ else if (executeEvaluationWithFile("lucky13sec3", file, test_arg))
+ {
+ std::string result_folder_sha1 = "results/lucky13sha1sec3";
+ std::unique_ptr<Lucky13Test> test_sha1(new Lucky13Test(inputs, result_folder_sha1, "SHA-1", 20));
+ test_sha1->execute_evaluation();
+ std::string result_folder_sha256 = "results/lucky13sha256sec3";
+ std::unique_ptr<Lucky13Test> test_sha256(new Lucky13Test(inputs, result_folder_sha256, "SHA-256", 32));
+ test_sha256->execute_evaluation();
+ }
+ else if (executeEvaluationWithFile("lucky13sec4sha1", file, test_arg))
+ {
+ std::string result_folder_sha1 = "results/lucky13sha1sec4";
+ std::unique_ptr<Lucky13Test> test_sha1(new Lucky13Test(inputs, result_folder_sha1, "SHA-1", 20));
+ test_sha1->execute_evaluation();
+ }
+ else if (executeEvaluationWithFile("lucky13sec4sha256", file, test_arg))
+ {
+ std::string result_folder_sha256 = "results/lucky13sha256sec4";
+ std::unique_ptr<Lucky13Test> test_sha256(new Lucky13Test(inputs, result_folder_sha256, "SHA-256", 32));
+ test_sha256->execute_evaluation();
+ }
+ else if (executeEvaluationWithFile("lucky13sha384", file, test_arg))
+ {
+ std::string result_folder_sha384 = "results/lucky13sha384";
+ std::unique_ptr<Lucky13Test> test_sha384(new Lucky13Test(inputs, result_folder_sha384, "SHA-384", 48));
+ test_sha384->execute_evaluation();
+ }
+ else
+ {
+ std::cout << "\nSkipping the following test: " << file;
+ }
+ }
+
+ return 1;
+ }