diff --git a/.gitmodules b/.gitmodules index 21b46eec..0e6e510c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = data-gui url = https://github.com/IAIK/data-gui.git branch = master +[submodule "cryptolib/botan/botan"] + path = cryptolib/botan/botan + url = https://github.com/randombit/botan.git diff --git a/cryptolib/botan/Makefile b/cryptolib/botan/Makefile new file mode 100644 index 00000000..98339d56 --- /dev/null +++ b/cryptolib/botan/Makefile @@ -0,0 +1,22 @@ +all: fetch configure build + +fetch: + git submodule update --init --recursive + +configure: + cd botan && \ + ./configure.py --prefix=./build --cc=gcc --cc-bin=g++-11 --cc-abi=-fno-plt \ + --disable-modules tls,locking_allocator --disable-sse2 --disable-ssse3 \ + --disable-sse4.1 --disable-sse4.2 --disable-avx2 --disable-bmi2 --disable-rdrand \ + --disable-rdseed --disable-aes-ni --disable-sha-ni --disable-altivec \ + --disable-neon --disable-armv8crypto --disable-powercrypto \ + --without-os-feature=threads --with-debug-info --build-targets=static,cli + +build: + $(MAKE) -C botan botan + $(MAKE) -C algo_dilithium + $(MAKE) -C algo_kyber + $(MAKE) -C algo_xmss + +clean: + make -C botan clean diff --git a/cryptolib/botan/algo_aes/.gitignore b/cryptolib/botan/algo_aes/.gitignore new file mode 100644 index 00000000..fbca2253 --- /dev/null +++ b/cryptolib/botan/algo_aes/.gitignore @@ -0,0 +1 @@ +results/ diff --git a/cryptolib/botan/algo_aes/data_run.sh b/cryptolib/botan/algo_aes/data_run.sh new file mode 100755 index 00000000..b28c4b5a --- /dev/null +++ b/cryptolib/botan/algo_aes/data_run.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} AES 128 CBC + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} AES 192 CBC +./framework.sh ${PINFLAGS} AES 256 CBC + +popd diff --git a/cryptolib/botan/algo_aes/framework.sh b/cryptolib/botan/algo_aes/framework.sh new file mode 100755 index 00000000..f3d793a6 --- /dev/null +++ b/cryptolib/botan/algo_aes/framework.sh @@ -0,0 +1,139 @@ + + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=300 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/../botan/botan + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/sym_byte_value.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + "${DATA_COMMON}"/genkey.py "${KEYBYTES}" > "$1" + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" + echo "hello" > input.bin + echo "LD_LIBRARY_PATH=${BINARY}" >> ${ENVFILE} +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + HEXKEY=$(cat "$1") + echo "${BINARY} cipher --cipher=${ALGO}-${PARAM}/${MODE} --key=${HEXKEY} input.bin" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + PARAM=$2 + MODE=$3 + SHIFT=$((SHIFT+2)) + KEYBYTES=$(( PARAM / 8 )) + + WORKDIR="$ALGO-$MODE-$PARAM" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_curve25519/.gitignore b/cryptolib/botan/algo_curve25519/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_curve25519/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_curve25519/Makefile b/cryptolib/botan/algo_curve25519/Makefile new file mode 100644 index 00000000..03fbd5a1 --- /dev/null +++ b/cryptolib/botan/algo_curve25519/Makefile @@ -0,0 +1,8 @@ +all: curve25519 + +curve25519: curve25519.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O0 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_curve25519/curve25519.cpp b/cryptolib/botan/algo_curve25519/curve25519.cpp new file mode 100644 index 00000000..b06ff2ce --- /dev/null +++ b/cryptolib/botan/algo_curve25519/curve25519.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +using namespace std; + + + +#include +#include +#include +#include +#include + +vector modes = { + "curve25519", +}; + +vector operations = { + "keygen", + "ecdh" +}; + +int main(int argc, char* argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " ecdh \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... ecc key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_keyfile (argv[3]); + + // ec domain and KDF + const std::string kdf = "KDF2(SHA-256)"; + + std::string keyfile_buffer_sk(str_keyfile); + + if (str_operation == "keygen") { + // KeyGen + const Botan::Curve25519_PrivateKey key(rng); + const auto key_bits = key.private_key_bits(); + + // Store key pair + ofstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + keyfile_sk << hex_encode(key_bits); + keyfile_sk.close(); + + } else if (str_operation == "ecdh") { + // std::vector signature; + string line_sk; + ifstream keyfile_sk; + + Botan::AlgorithmIdentifier aid; + + // // Load server key + Botan::Curve25519_PrivateKey server_key( + aid, + Botan::hex_decode( + "042014F9395B906AD12E57E10E0CC0694A747322B6FFEF4B8FB3803F6F2AFE972B2C" + ) + ); + // keyfile_sk.open(keyfile_buffer_sk); + // getline(keyfile_sk, line_sk); + // keyfile_sk.close(); + // const auto server_sk(Botan::hex_decode(line_sk)); + // Botan::Curve25519_PrivateKey server_key(aid, server_sk); + + // Load experiment key + keyfile_sk.open(keyfile_buffer_sk); + getline(keyfile_sk, line_sk); + keyfile_sk.close(); + const auto sk(Botan::hex_decode(line_sk)); + Botan::Curve25519_PrivateKey key(aid, sk); + + // now they exchange their public values + const auto server_key_pub = server_key.public_value(); + const auto key_pub = key.public_value(); + + // Construct key agreements and agree on a shared secret + Botan::PK_Key_Agreement ka_server(server_key, rng, kdf); + const auto sA = ka_server.derive_key(32, key_pub).bits_of(); + + Botan::PK_Key_Agreement ka_client(key, rng, kdf); + const auto sB = ka_client.derive_key(32, server_key_pub).bits_of(); + + assert(sA == sB); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} diff --git a/cryptolib/botan/algo_curve25519/data_run.sh b/cryptolib/botan/algo_curve25519/data_run.sh new file mode 100755 index 00000000..1937a402 --- /dev/null +++ b/cryptolib/botan/algo_curve25519/data_run.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} curve25519 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + + +./framework.sh ${PINFLAGS} secp256r1 + +popd diff --git a/cryptolib/botan/algo_curve25519/framework.sh b/cryptolib/botan/algo_curve25519/framework.sh new file mode 100755 index 00000000..28046994 --- /dev/null +++ b/cryptolib/botan/algo_curve25519/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=30 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/curve25519 + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} ecdh $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="ecdh-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_des/.gitignore b/cryptolib/botan/algo_des/.gitignore new file mode 100644 index 00000000..fbca2253 --- /dev/null +++ b/cryptolib/botan/algo_des/.gitignore @@ -0,0 +1 @@ +results/ diff --git a/cryptolib/botan/algo_des/data_run.sh b/cryptolib/botan/algo_des/data_run.sh new file mode 100755 index 00000000..cad78b74 --- /dev/null +++ b/cryptolib/botan/algo_des/data_run.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} DES 64 CBC + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} 3DES 192 CBC + +popd diff --git a/cryptolib/botan/algo_des/framework.sh b/cryptolib/botan/algo_des/framework.sh new file mode 100755 index 00000000..7f65ad80 --- /dev/null +++ b/cryptolib/botan/algo_des/framework.sh @@ -0,0 +1,139 @@ + + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=300 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/../botan/botan + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/sym_byte_value.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + "${DATA_COMMON}"/genkey.py "${KEYBYTES}" > "$1" + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" + echo "hello" > input.bin + echo "LD_LIBRARY_PATH=${BINARY}" >> ${ENVFILE} +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + HEXKEY=$(cat "$1") + echo "${BINARY} cipher --cipher=${ALGO}/${MODE} --key=${HEXKEY} input.bin" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + PARAM=$2 + MODE=$3 + SHIFT=$((SHIFT+2)) + KEYBYTES=$(( PARAM / 8 )) + + WORKDIR="$ALGO-$MODE-$PARAM" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_dilithium/.gitignore b/cryptolib/botan/algo_dilithium/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_dilithium/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_dilithium/Makefile b/cryptolib/botan/algo_dilithium/Makefile new file mode 100644 index 00000000..7b3a913b --- /dev/null +++ b/cryptolib/botan/algo_dilithium/Makefile @@ -0,0 +1,8 @@ +all: dilithium + +dilithium: dilithium.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_dilithium/data_run.sh b/cryptolib/botan/algo_dilithium/data_run.sh new file mode 100755 index 00000000..ece51959 --- /dev/null +++ b/cryptolib/botan/algo_dilithium/data_run.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} 4x4 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} 4x4_AES +./framework.sh ${PINFLAGS} 6x5 +./framework.sh ${PINFLAGS} 6x5_AES +./framework.sh ${PINFLAGS} 8x7 +./framework.sh ${PINFLAGS} 8x7_AES + +popd diff --git a/cryptolib/botan/algo_dilithium/dilithium.cpp b/cryptolib/botan/algo_dilithium/dilithium.cpp new file mode 100644 index 00000000..28616b84 --- /dev/null +++ b/cryptolib/botan/algo_dilithium/dilithium.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include + +vector modes = { + "4x4", "4x4_AES", "6x5", "6x5_AES", "8x7", "8x7_AES", +}; + +vector operations = {"keygen", "sign"}; + +Botan::DilithiumMode name_to_mode(const std::string &algo_name) { + if (algo_name == "4x4") { + return Botan::DilithiumMode::Dilithium4x4; + } + if (algo_name == "4x4_AES") { + return Botan::DilithiumMode::Dilithium4x4_AES; + } + if (algo_name == "6x5") { + return Botan::DilithiumMode::Dilithium6x5; + } + if (algo_name == "6x5_AES") { + return Botan::DilithiumMode::Dilithium6x5_AES; + } + if (algo_name == "8x7") { + return Botan::DilithiumMode::Dilithium8x7; + } + if (algo_name == "8x7_AES") { + return Botan::DilithiumMode::Dilithium8x7_AES; + } + + assert(false); +} + +int main(int argc, char *argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " dilithium \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or " + "kem\n" + << " ... kyber key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for (vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for (vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode(argv[1]); + string str_operation(argv[2]); + string str_keyfile(argv[3]); + + Botan::DilithiumMode mode = name_to_mode(str_mode); + // auto encoding = Botan::DilithiumKeyEncoding::DER; + auto encoding = Botan::DilithiumKeyEncoding::Raw; + + std::string keyfile_buffer_sk(str_keyfile); + + if (str_operation == "keygen") { + const Botan::Dilithium_PrivateKey priv_key(rng, mode); + const auto priv_key_bits = priv_key.private_key_bits(); + + ofstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + keyfile_sk << Botan::hex_encode(priv_key_bits); + keyfile_sk.close(); + } else if (str_operation == "sign") { + std::vector message, signature; + message.push_back(0xde); + message.push_back(0xad); + message.push_back(0xbe); + message.push_back(0xef); + + // Load key pair + string line_sk; + ifstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + getline(keyfile_sk, line_sk); + keyfile_sk.close(); + Botan::secure_vector priv_key_bits = + Botan::hex_decode_locked(line_sk); + + Botan::Dilithium_PrivateKey priv_key(priv_key_bits, mode, encoding); + + Botan::PK_Signer sig(priv_key, rng, "Deterministic"); + signature = sig.sign_message(message, rng); + + // Botan::PK_Verifier ver(priv_key, ""); + // ver.update(message); + // assert(ver.check_signature(signature)); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} diff --git a/cryptolib/botan/algo_dilithium/framework.sh b/cryptolib/botan/algo_dilithium/framework.sh new file mode 100755 index 00000000..a79134f4 --- /dev/null +++ b/cryptolib/botan/algo_dilithium/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/dilithium + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +# export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} sign $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="dilithium-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_ecc/.gitignore b/cryptolib/botan/algo_ecc/.gitignore new file mode 100644 index 00000000..fbca2253 --- /dev/null +++ b/cryptolib/botan/algo_ecc/.gitignore @@ -0,0 +1 @@ +results/ diff --git a/cryptolib/botan/algo_ecc/data_run.sh b/cryptolib/botan/algo_ecc/data_run.sh new file mode 100755 index 00000000..f8a11838 --- /dev/null +++ b/cryptolib/botan/algo_ecc/data_run.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} ECDSA brainpool192r1 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} ECDSA brainpool256r1 +./framework.sh ${PINFLAGS} ECDSA brainpool384r1 +./framework.sh ${PINFLAGS} ECDSA brainpool512r1 + +popd diff --git a/cryptolib/botan/algo_ecc/framework.sh b/cryptolib/botan/algo_ecc/framework.sh new file mode 100755 index 00000000..ec63c20a --- /dev/null +++ b/cryptolib/botan/algo_ecc/framework.sh @@ -0,0 +1,143 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/../botan/botan + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} keygen --algo=${ALGO} --params=${PARAM} > "$1" + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" + echo "hello" > input.bin +# ${BINARY} keygen --algo=${ALGO} --params=${PARAM} > static.key +# echo "-----BEGIN PRIVATE KEY----- +# MHACAQAwFAYHKoZIzj0CAQYJKyQDAwIIAQEDBFUwUwIBAQQYgI65v9ekZ52wFCBB +# mkEh438fE/ZznC5NoTQDMgAEbDFsJx0BRmz14NKpz7LUyskxdhD0ndaKvbaHeU8r +# S+VwHHPerR2Sbs2HiRfZ1gU5 +# -----END PRIVATE KEY-----" > static.key + echo "LD_LIBRARY_PATH=${BINARY}" >> ${ENVFILE} +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} sign $1 input.bin" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + PARAM=$2 + SHIFT=$((SHIFT+1)) + KEYBYTES=$(( PARAM / 8 )) + + WORKDIR="$ALGO-$PARAM" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_ecdh/.gitignore b/cryptolib/botan/algo_ecdh/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_ecdh/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_ecdh/Makefile b/cryptolib/botan/algo_ecdh/Makefile new file mode 100644 index 00000000..ed68f9ae --- /dev/null +++ b/cryptolib/botan/algo_ecdh/Makefile @@ -0,0 +1,8 @@ +all: ecdh + +ecdh: ecdh.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_ecdh/data_run.sh b/cryptolib/botan/algo_ecdh/data_run.sh new file mode 100755 index 00000000..ab70813b --- /dev/null +++ b/cryptolib/botan/algo_ecdh/data_run.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} secp256r1 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} + +popd diff --git a/cryptolib/botan/algo_ecdh/ecdh.cpp b/cryptolib/botan/algo_ecdh/ecdh.cpp new file mode 100644 index 00000000..ffcc35ed --- /dev/null +++ b/cryptolib/botan/algo_ecdh/ecdh.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +using namespace std; + + + +#include +#include +#include +#include +#include + +// #include +// #include +// #include +// #include +// #include + +vector modes = { + "secp256r1", +}; + +vector operations = { + "keygen", + "ecdh" +}; + +int main(int argc, char* argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " ecdh \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... ecc key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_keyfile (argv[3]); + + // ec domain and KDF + Botan::EC_Group domain(str_mode); + const std::string kdf = "KDF2(SHA-256)"; + + std::string keyfile_buffer_sk(str_keyfile); + + if (str_operation == "keygen") { + // KeyGen + const Botan::ECDH_PrivateKey key(rng, domain); + const Botan::BigInt key_bigint = key.private_value(); + + // Store key pair + ofstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + keyfile_sk << key_bigint.to_hex_string(); + keyfile_sk.close(); + + } else if (str_operation == "ecdh") { + // std::vector signature; + string line_sk; + ifstream keyfile_sk; + + const Botan::AlgorithmIdentifier aid = Botan::AlgorithmIdentifier(); + + // Load server key + keyfile_sk.open("server_key"); + getline(keyfile_sk, line_sk); + keyfile_sk.close(); + Botan::BigInt server_key_bigint(line_sk); + Botan::ECDH_PrivateKey server_key(rng, domain, server_key_bigint); + + // Load experiment key + keyfile_sk.open(keyfile_buffer_sk); + getline(keyfile_sk, line_sk); + keyfile_sk.close(); + Botan::BigInt key_bigint(line_sk); + Botan::ECDH_PrivateKey key(rng, domain, key_bigint); + + // now they exchange their public values + const auto server_key_pub = server_key.public_value(); + const auto key_pub = key.public_value(); + + // Construct key agreements and agree on a shared secret + Botan::PK_Key_Agreement ka_server(server_key, rng, kdf); + const auto sA = ka_server.derive_key(32, key_pub).bits_of(); + + Botan::PK_Key_Agreement ka_client(key, rng, kdf); + const auto sB = ka_client.derive_key(32, server_key_pub).bits_of(); + + assert(sA == sB); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} diff --git a/cryptolib/botan/algo_ecdh/framework.sh b/cryptolib/botan/algo_ecdh/framework.sh new file mode 100755 index 00000000..c231c4d3 --- /dev/null +++ b/cryptolib/botan/algo_ecdh/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/ecdh + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + ${BINARY} ${ALGO} keygen server_key +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} ecdh $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="ecdh-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_frodokem/.gitignore b/cryptolib/botan/algo_frodokem/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_frodokem/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_frodokem/Makefile b/cryptolib/botan/algo_frodokem/Makefile new file mode 100644 index 00000000..b8136956 --- /dev/null +++ b/cryptolib/botan/algo_frodokem/Makefile @@ -0,0 +1,8 @@ +all: frodokem + +frodokem: frodokem.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_frodokem/data_run.sh b/cryptolib/botan/algo_frodokem/data_run.sh new file mode 100755 index 00000000..54996deb --- /dev/null +++ b/cryptolib/botan/algo_frodokem/data_run.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=/new_data/ssd1/data/wagner/bsi/DATA/results/algo_frodokem + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf $RESULTDIR +fi + +./framework.sh ${PINFLAGS} KEM640_SHAKE + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} KEM976_SHAKE +./framework.sh ${PINFLAGS} KEM1344_SHAKE +./framework.sh ${PINFLAGS} eKEM640_SHAKE +./framework.sh ${PINFLAGS} eKEM976_SHAKE +./framework.sh ${PINFLAGS} eKEM1344_SHAKE + +./framework.sh ${PINFLAGS} KEM640_AES +./framework.sh ${PINFLAGS} KEM976_AES +./framework.sh ${PINFLAGS} KEM1344_AES +./framework.sh ${PINFLAGS} eKEM640_AES +./framework.sh ${PINFLAGS} eKEM976_AES +./framework.sh ${PINFLAGS} eKEM1344_AES + +popd diff --git a/cryptolib/botan/algo_frodokem/framework.sh b/cryptolib/botan/algo_frodokem/framework.sh new file mode 100755 index 00000000..19e346ad --- /dev/null +++ b/cryptolib/botan/algo_frodokem/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/frodokem + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} kem $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="frodoKEM-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_frodokem/frodokem.cpp b/cryptolib/botan/algo_frodokem/frodokem.cpp new file mode 100644 index 00000000..9729851c --- /dev/null +++ b/cryptolib/botan/algo_frodokem/frodokem.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include + +vector modes = { + "KEM640_SHAKE", +}; + +vector operations = { + "keygen", + "kem" +}; + +const size_t shared_secret_length = 32; + +Botan::FrodoKEMMode name_to_mode(const std::string& algo_name) { + if(algo_name == "KEM640_SHAKE") + { return Botan::FrodoKEMMode::FrodoKEM640_SHAKE; } + if(algo_name == "KEM976_SHAKE") + { return Botan::FrodoKEMMode::FrodoKEM976_SHAKE; } + if(algo_name == "KEM1344_SHAKE") + { return Botan::FrodoKEMMode::FrodoKEM1344_SHAKE; } + if(algo_name == "eKEM640_SHAKE") + { return Botan::FrodoKEMMode::eFrodoKEM640_SHAKE; } + if(algo_name == "eKEM976_SHAKE") + { return Botan::FrodoKEMMode::eFrodoKEM976_SHAKE; } + if(algo_name == "eKEM1344_SHAKE") + { return Botan::FrodoKEMMode::eFrodoKEM1344_SHAKE; } + if(algo_name == "KEM640_AES") + { return Botan::FrodoKEMMode::FrodoKEM640_AES; } + if(algo_name == "KEM976_AES") + { return Botan::FrodoKEMMode::FrodoKEM976_AES; } + if(algo_name == "KEM1344_AES") + { return Botan::FrodoKEMMode::FrodoKEM1344_AES; } + if(algo_name == "eKEM640_AES") + { return Botan::FrodoKEMMode::eFrodoKEM640_AES; } + if(algo_name == "eKEM976_AES") + { return Botan::FrodoKEMMode::eFrodoKEM976_AES; } + if(algo_name == "eKEM1344_AES") + { return Botan::FrodoKEMMode::eFrodoKEM1344_AES; } + + assert(false); +} + +void frodokem_encrypt( + Botan::FrodoKEM_PublicKey pub_key, + Botan::secure_vector &cipher_text, + Botan::secure_vector &sym_key + ) { + Botan::AutoSeeded_RNG rng; + auto encryptor = Botan::PK_KEM_Encryptor(pub_key, "KDF2(SHA-256)", ""); + encryptor.encrypt(cipher_text, sym_key, rng, shared_secret_length); +} + +void frodokem_decrypt( + Botan::FrodoKEM_PrivateKey priv_key, + Botan::secure_vector &cipher_text, + Botan::secure_vector &sym_key + ) { + Botan::AutoSeeded_RNG rng; + auto decryptor = Botan::PK_KEM_Decryptor(priv_key, rng, "KDF2(SHA-256)", ""); + sym_key = decryptor.decrypt(cipher_text.data(), cipher_text.size(), shared_secret_length); +} + +int main(int argc, char* argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " frodokem \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... frodokem key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_frodokemkeyfile (argv[3]); + + Botan::FrodoKEMMode mode = name_to_mode(str_mode); + + std::string frodokemkeyfile_buffer_sk(str_frodokemkeyfile); + + if (str_operation == "keygen") { + // Alice KeyGen + const Botan::FrodoKEM_PrivateKey priv_key(rng, mode); + const auto priv_key_bits = priv_key.private_key_bits(); + + // Store key pair + ofstream frodokemkeyfile_sk; + frodokemkeyfile_sk.open(frodokemkeyfile_buffer_sk); + frodokemkeyfile_sk << Botan::hex_encode(priv_key_bits); + frodokemkeyfile_sk.close(); + } else if (str_operation == "kem") { + Botan::secure_vector cipher_text, key_bob, key_alice; + + // Load key pair + string line_sk; + ifstream frodokemkeyfile_sk; + frodokemkeyfile_sk.open(frodokemkeyfile_buffer_sk); + getline(frodokemkeyfile_sk, line_sk); + frodokemkeyfile_sk.close(); + Botan::secure_vector priv_key_bits = Botan::hex_decode_locked(line_sk); + + Botan::FrodoKEM_PrivateKey priv_key(priv_key_bits, mode); + const auto pk = priv_key.public_key(); + const auto pk_bits = pk->public_key_bits(); + Botan::FrodoKEM_PublicKey pub_key(pk_bits, mode); + + frodokem_encrypt(pub_key, cipher_text, key_bob); + frodokem_decrypt(priv_key, cipher_text, key_alice); + + assert(key_bob == key_alice); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} + diff --git a/cryptolib/botan/algo_kyber/.gitignore b/cryptolib/botan/algo_kyber/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_kyber/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_kyber/Makefile b/cryptolib/botan/algo_kyber/Makefile new file mode 100644 index 00000000..58bb9ee2 --- /dev/null +++ b/cryptolib/botan/algo_kyber/Makefile @@ -0,0 +1,8 @@ +all: kyber + +kyber: kyber.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_kyber/data_run.sh b/cryptolib/botan/algo_kyber/data_run.sh new file mode 100755 index 00000000..00b53246 --- /dev/null +++ b/cryptolib/botan/algo_kyber/data_run.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} 512 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} 512-90s +./framework.sh ${PINFLAGS} 768 +./framework.sh ${PINFLAGS} 768-90s +./framework.sh ${PINFLAGS} 1024 +./framework.sh ${PINFLAGS} 1024-90s + +popd diff --git a/cryptolib/botan/algo_kyber/framework.sh b/cryptolib/botan/algo_kyber/framework.sh new file mode 100755 index 00000000..24dfc9ad --- /dev/null +++ b/cryptolib/botan/algo_kyber/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/kyber + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} kem $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="kyber-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_kyber/kyber.cpp b/cryptolib/botan/algo_kyber/kyber.cpp new file mode 100644 index 00000000..7586fa58 --- /dev/null +++ b/cryptolib/botan/algo_kyber/kyber.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include + +vector modes = { + "512", + "512-90s", + "768", + "768-90s", + "1024", + "1024-90s" +}; + +vector operations = { + "keygen", + "kem" +}; + +const size_t shared_secret_length = 32; + +Botan::KyberMode name_to_mode(const std::string& algo_name) { + if(algo_name == "Kyber-512") + { return Botan::KyberMode::Kyber512; } + if(algo_name == "Kyber-512-90s") + { return Botan::KyberMode::Kyber512_90s; } + if(algo_name == "Kyber-768") + { return Botan::KyberMode::Kyber768; } + if(algo_name == "Kyber-768-90s") + { return Botan::KyberMode::Kyber768_90s; } + if(algo_name == "Kyber-1024") + { return Botan::KyberMode::Kyber1024; } + if(algo_name == "Kyber-1024-90s") + { return Botan::KyberMode::Kyber1024_90s; } + + assert(false); +} + +void kyber_kem_encrypt( + Botan::Kyber_PublicKey pub_key, + Botan::secure_vector &cipher_text, + Botan::secure_vector &sym_key + ) { + Botan::AutoSeeded_RNG rng; + auto encryptor = Botan::PK_KEM_Encryptor(pub_key, rng, "HKDF(SHA-256)", ""); + encryptor.encrypt(cipher_text, sym_key, shared_secret_length, rng); +} + +void kyber_kem_decrypt( + Botan::Kyber_PrivateKey priv_key, + Botan::secure_vector &cipher_text, + Botan::secure_vector &sym_key + ) { + Botan::AutoSeeded_RNG rng; + auto decryptor = Botan::PK_KEM_Decryptor(priv_key, rng, "HKDF(SHA-256)", ""); + sym_key = decryptor.decrypt(cipher_text.data(), cipher_text.size(), shared_secret_length); +} + +int main(int argc, char* argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " kyber \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... kyber key file, read as text\n" + // << " ..... symmetric key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_kyberkeyfile (argv[3]); + + std::string mode_buffer("Kyber-"); + mode_buffer.append(str_mode); + Botan::KyberMode mode = name_to_mode(mode_buffer); + + std::string kyberkeyfile_buffer_sk(str_kyberkeyfile); + + if (str_operation == "keygen") { + // Alice KeyGen + const Botan::Kyber_PrivateKey priv_key(rng, mode); + const auto priv_key_bits = priv_key.private_key_bits(); + + // Store key pair + ofstream kyberkeyfile_sk; + kyberkeyfile_sk.open(kyberkeyfile_buffer_sk); + kyberkeyfile_sk << Botan::hex_encode(priv_key_bits); + kyberkeyfile_sk.close(); + } else if (str_operation == "kem") { + Botan::secure_vector cipher_text, key_bob, key_alice; + + // Load key pair + string line_sk; + ifstream kyberkeyfile_sk; + kyberkeyfile_sk.open(kyberkeyfile_buffer_sk); + getline(kyberkeyfile_sk, line_sk); + kyberkeyfile_sk.close(); + Botan::secure_vector priv_key_bits = Botan::hex_decode_locked(line_sk); + + Botan::Kyber_PrivateKey priv_key(priv_key_bits, mode, Botan::KyberKeyEncoding::Full); + const auto pk = priv_key.public_key(); + const auto pk_bits = pk->public_key_bits(); + Botan::Kyber_PublicKey pub_key(pk_bits, mode, Botan::KyberKeyEncoding::Full); + + kyber_kem_encrypt(pub_key, cipher_text, key_bob); + kyber_kem_decrypt(priv_key, cipher_text, key_alice); + + // assert(key_bob == key_alice); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} + diff --git a/cryptolib/botan/algo_lms/.gitignore b/cryptolib/botan/algo_lms/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_lms/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_lms/Makefile b/cryptolib/botan/algo_lms/Makefile new file mode 100644 index 00000000..5203c5da --- /dev/null +++ b/cryptolib/botan/algo_lms/Makefile @@ -0,0 +1,8 @@ +all: lms + +lms: lms.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_lms/data_run.sh b/cryptolib/botan/algo_lms/data_run.sh new file mode 100755 index 00000000..324ca8a2 --- /dev/null +++ b/cryptolib/botan/algo_lms/data_run.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} "Truncated(SHA-256,192),HW(5,1)" + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +popd diff --git a/cryptolib/botan/algo_lms/framework.sh b/cryptolib/botan/algo_lms/framework.sh new file mode 100755 index 00000000..51e24abe --- /dev/null +++ b/cryptolib/botan/algo_lms/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/lms + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} sign $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="lms-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_lms/lms.cpp b/cryptolib/botan/algo_lms/lms.cpp new file mode 100644 index 00000000..5b5fa72a --- /dev/null +++ b/cryptolib/botan/algo_lms/lms.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include + +vector modes = { + "SHA-256,HW(5,1)", + "Truncated(SHA-256,192),HW(5,1)", +}; + +vector operations = { + "keygen", + "sign" +}; + +int main(int argc, char* argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " kyber \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... kyber key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_keyfile (argv[3]); + + // const Botan::HSS_LMS_Params hss_params(str_mode); + + std::string keyfile_buffer_sk(str_keyfile); + + if (str_operation == "keygen") { + // Alice KeyGen + auto sk = Botan::HSS_LMS_PrivateKey(rng, str_mode); + const auto sk_bits = sk.private_key_bits(); + + // Store key pair + ofstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + keyfile_sk << Botan::hex_encode(sk_bits); + keyfile_sk.close(); + } else if (str_operation == "sign") { + std::vector signature; + // auto message = Botan::hex_decode("deadbeef"); + auto message = rng.random_vec(32); + + // Load key pair + string line_sk; + ifstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + getline(keyfile_sk, line_sk); + keyfile_sk.close(); + Botan::secure_vector priv_key_bits = + Botan::hex_decode_locked(line_sk); + + Botan::HSS_LMS_PrivateKey priv_key(priv_key_bits); + + Botan::PK_Signer sig(priv_key, rng, ""); + signature = sig.sign_message(message, rng); + + Botan::PK_Verifier ver(priv_key, ""); + ver.update(message); + assert(ver.check_signature(signature)); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} + diff --git a/cryptolib/botan/algo_mceliece/.gitignore b/cryptolib/botan/algo_mceliece/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_mceliece/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_mceliece/Makefile b/cryptolib/botan/algo_mceliece/Makefile new file mode 100644 index 00000000..92f19031 --- /dev/null +++ b/cryptolib/botan/algo_mceliece/Makefile @@ -0,0 +1,8 @@ +all: cmce + +cmce: cmce.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include/public -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_mceliece/cmce.cpp b/cryptolib/botan/algo_mceliece/cmce.cpp new file mode 100644 index 00000000..946b8d03 --- /dev/null +++ b/cryptolib/botan/algo_mceliece/cmce.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include + +vector modes = { + "mceliece348864", + "mceliece348864f", +}; + +vector operations = { + "keygen", + "kem" +}; + +const size_t shared_secret_length = 32; + +void mceliece_encrypt( + Botan::Classic_McEliece_PrivateKey priv_key, + Botan::secure_vector &cipher_text, + Botan::secure_vector &sym_key + ) { + Botan::AutoSeeded_RNG rng; + auto encryptor = Botan::PK_KEM_Encryptor(priv_key, "Raw", "base"); + encryptor.encrypt(cipher_text, sym_key, rng, shared_secret_length); +} + +void mceliece_decrypt( + Botan::Classic_McEliece_PrivateKey priv_key, + Botan::secure_vector &cipher_text, + Botan::secure_vector &sym_key + ) { + Botan::AutoSeeded_RNG rng; + auto decryptor = Botan::PK_KEM_Decryptor(priv_key, rng, "Raw"); + sym_key = decryptor.decrypt(cipher_text.data(), cipher_text.size(), shared_secret_length); +} + +int main(int argc, char* argv[]) { + if (argc != 4) { + cout << "Usage:\n\n" + << " mceliece \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... mceliece key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_mceliecekeyfile (argv[3]); + + Botan::Classic_McEliece_Parameter_Set params = Botan::cmce_param_set_from_str(str_mode); + + std::string mceliecekeyfile_buffer_sk(str_mceliecekeyfile); + + if (str_operation == "keygen") { + Botan::AutoSeeded_RNG rng; + // Alice KeyGen + const Botan::Classic_McEliece_PrivateKey priv_key(rng, params); + const auto priv_key_bits = priv_key.private_key_bits(); + + // Store key pair + ofstream mceliecekeyfile_sk; + mceliecekeyfile_sk.open(mceliecekeyfile_buffer_sk); + mceliecekeyfile_sk << Botan::hex_encode(priv_key_bits); + mceliecekeyfile_sk.close(); + } else if (str_operation == "kem") { + Botan::secure_vector cipher_text, key_bob, key_alice; + + // Load key pair + string line_sk; + ifstream mceliecekeyfile_sk; + mceliecekeyfile_sk.open(mceliecekeyfile_buffer_sk); + getline(mceliecekeyfile_sk, line_sk); + mceliecekeyfile_sk.close(); + Botan::secure_vector priv_key_bits = Botan::hex_decode_locked(line_sk); + + Botan::Classic_McEliece_PrivateKey priv_key(priv_key_bits, params); + + mceliece_encrypt(priv_key, cipher_text, key_bob); + mceliece_decrypt(priv_key, cipher_text, key_alice); + + assert(key_bob == key_alice); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} + diff --git a/cryptolib/botan/algo_mceliece/data_run.sh b/cryptolib/botan/algo_mceliece/data_run.sh new file mode 100755 index 00000000..173e93b6 --- /dev/null +++ b/cryptolib/botan/algo_mceliece/data_run.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +# PINFLAGS="--phase1 --export" +PINFLAGS="--phase1 --phase2 --export --parallel" +# PINFLAGS="--phase1 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf $RESULTDIR +fi + +./framework.sh ${PINFLAGS} minimal + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} mceliece348864 +./framework.sh ${PINFLAGS} mceliece6688128 +./framework.sh ${PINFLAGS} mceliece6688128f +./framework.sh ${PINFLAGS} mceliece6688128pc +./framework.sh ${PINFLAGS} mceliece6688128pcf + +popd diff --git a/cryptolib/botan/algo_mceliece/framework.sh b/cryptolib/botan/algo_mceliece/framework.sh new file mode 100755 index 00000000..c3837f23 --- /dev/null +++ b/cryptolib/botan/algo_mceliece/framework.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=10 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +# export BINARY=/home/wagner/workspace/bsi/DATA/cryptolib/botan/botan/botan-test +export BINARY=${PWD}/bin/cmce + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + # ${BINARY} ${ALGO} keygen $1 + touch $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "/home/wagner/botan/DATA/cryptolib/botan/botan/botan-test cmce_minimal --test-threads=1 --no-stdout" + # echo "${BINARY} ${ALGO} keygen $1" + # echo "${BINARY} ${ALGO} kem $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="cmce-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_rsa/.gitignore b/cryptolib/botan/algo_rsa/.gitignore new file mode 100644 index 00000000..fbca2253 --- /dev/null +++ b/cryptolib/botan/algo_rsa/.gitignore @@ -0,0 +1 @@ +results/ diff --git a/cryptolib/botan/algo_rsa/data_run.sh b/cryptolib/botan/algo_rsa/data_run.sh new file mode 100755 index 00000000..0ed24bc8 --- /dev/null +++ b/cryptolib/botan/algo_rsa/data_run.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} RSA 1024 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} RSA 2048 +./framework.sh ${PINFLAGS} RSA 3072 + +popd diff --git a/cryptolib/botan/algo_rsa/framework.sh b/cryptolib/botan/algo_rsa/framework.sh new file mode 100755 index 00000000..f970cd2d --- /dev/null +++ b/cryptolib/botan/algo_rsa/framework.sh @@ -0,0 +1,138 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=300 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/../botan/botan + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} keygen --algo=${ALGO} --params=${PARAM} > "$1" + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" + echo "hello" > input.bin + echo "LD_LIBRARY_PATH=${BINARY}" >> ${ENVFILE} + echo "BOTAN_THREAD_POOL_SIZE=none" >> ${ENVFILE} +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} sign $1 input.bin" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + PARAM=$2 + SHIFT=$((SHIFT+1)) + KEYBYTES=$(( PARAM / 8 )) + + WORKDIR="$ALGO-$PARAM" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_xmss/.gitignore b/cryptolib/botan/algo_xmss/.gitignore new file mode 100644 index 00000000..12941761 --- /dev/null +++ b/cryptolib/botan/algo_xmss/.gitignore @@ -0,0 +1,2 @@ +bin/ +results/ diff --git a/cryptolib/botan/algo_xmss/Makefile b/cryptolib/botan/algo_xmss/Makefile new file mode 100644 index 00000000..8496a616 --- /dev/null +++ b/cryptolib/botan/algo_xmss/Makefile @@ -0,0 +1,8 @@ +all: xmss + +xmss: xmss.cpp + mkdir -p bin + g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a + +clean: + rm -rf bin/ diff --git a/cryptolib/botan/algo_xmss/botan_xmss.patch b/cryptolib/botan/algo_xmss/botan_xmss.patch new file mode 100644 index 00000000..930cc104 --- /dev/null +++ b/cryptolib/botan/algo_xmss/botan_xmss.patch @@ -0,0 +1,93 @@ +diff --git a/src/lib/pubkey/xmss/xmss_hash.cpp b/src/lib/pubkey/xmss/xmss_hash.cpp +index 957e9e989..f14c3a305 100644 +--- a/src/lib/pubkey/xmss/xmss_hash.cpp ++++ b/src/lib/pubkey/xmss/xmss_hash.cpp +@@ -40,8 +40,8 @@ void XMSS_Hash::h_msg_init(std::span randomness, + m_msg_hash->clear(); + m_msg_hash->update(m_zero_padding); + m_msg_hash->update(0x02); +- m_msg_hash->update(randomness.data(), randomness.size()); +- m_msg_hash->update(root.data(), root.size()); ++ // m_msg_hash->update(randomness.data(), randomness.size()); ++ // m_msg_hash->update(root.data(), root.size()); + m_msg_hash->update(index_bytes.data(), index_bytes.size()); + } + +diff --git a/src/lib/pubkey/xmss/xmss_parameters.cpp b/src/lib/pubkey/xmss/xmss_parameters.cpp +index b53f6eaed..d5c0790e4 100644 +--- a/src/lib/pubkey/xmss/xmss_parameters.cpp ++++ b/src/lib/pubkey/xmss/xmss_parameters.cpp +@@ -30,6 +30,8 @@ XMSS_Parameters::xmss_algorithm_t XMSS_Parameters::xmss_id_from_string(const std + { return XMSS_SHA2_16_512; } + if(param_set == "XMSS-SHA2_20_512") + { return XMSS_SHA2_20_512; } ++ if(param_set == "XMSS-SHAKE_2_256") ++ { return XMSS_SHAKE_2_256; } + if(param_set == "XMSS-SHAKE_10_256") + { return XMSS_SHAKE_10_256; } + if(param_set == "XMSS-SHAKE_16_256") +@@ -42,6 +44,8 @@ XMSS_Parameters::xmss_algorithm_t XMSS_Parameters::xmss_id_from_string(const std + { return XMSS_SHAKE_16_512; } + if(param_set == "XMSS-SHAKE_20_512") + { return XMSS_SHAKE_20_512; } ++ if(param_set == "XMSS-SHA2_2_192") ++ { return XMSS_SHA2_2_192; } + if(param_set == "XMSS-SHA2_10_192") + { return XMSS_SHA2_10_192; } + if(param_set == "XMSS-SHA2_16_192") +@@ -139,6 +143,17 @@ XMSS_Parameters::XMSS_Parameters(xmss_algorithm_t oid) + m_strength = 512; + m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHA2_512; + break; ++ case XMSS_SHAKE_2_256: ++ m_element_size = 32; ++ m_hash_id_size = 32; ++ m_w = 16; ++ m_len = 67; ++ m_tree_height = 2; ++ m_name = "XMSS-SHAKE_2_256"; ++ m_hash_name = "SHAKE-128(256)"; ++ m_strength = 256; ++ m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHAKE_256; ++ break; + case XMSS_SHAKE_10_256: + m_element_size = 32; + m_hash_id_size = 32; +@@ -205,6 +220,17 @@ XMSS_Parameters::XMSS_Parameters(xmss_algorithm_t oid) + m_strength = 512; + m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHAKE_512; + break; ++ case XMSS_SHA2_2_192: ++ m_element_size = 24; ++ m_hash_id_size = 4; ++ m_w = 16; ++ m_len = 51; ++ m_tree_height = 2; ++ m_name = "XMSS-SHA2_2_192"; ++ m_hash_name = "Truncated(SHA-256,192)"; ++ m_strength = 192; ++ m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHA2_192; ++ break; + case XMSS_SHA2_10_192: + m_element_size = 24; + m_hash_id_size = 4; +diff --git a/src/lib/pubkey/xmss/xmss_parameters.h b/src/lib/pubkey/xmss/xmss_parameters.h +index 27564390a..f1275f57f 100644 +--- a/src/lib/pubkey/xmss/xmss_parameters.h ++++ b/src/lib/pubkey/xmss/xmss_parameters.h +@@ -149,6 +149,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_Parameters + XMSS_SHA2_10_512 = 0x00000004, + XMSS_SHA2_16_512 = 0x00000005, + XMSS_SHA2_20_512 = 0x00000006, ++ XMSS_SHAKE_2_256 = 0x000000f7, + XMSS_SHAKE_10_256 = 0x00000007, + XMSS_SHAKE_16_256 = 0x00000008, + XMSS_SHAKE_20_256 = 0x00000009, +@@ -157,6 +158,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_Parameters + XMSS_SHAKE_20_512 = 0x0000000c, + + // from NIST SP.800-208 ++ XMSS_SHA2_2_192 = 0x000000fd, + XMSS_SHA2_10_192 = 0x0000000d, + XMSS_SHA2_16_192 = 0x0000000e, + XMSS_SHA2_20_192 = 0x0000000f, diff --git a/cryptolib/botan/algo_xmss/data_run.sh b/cryptolib/botan/algo_xmss/data_run.sh new file mode 100755 index 00000000..baa6a29f --- /dev/null +++ b/cryptolib/botan/algo_xmss/data_run.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +PINFLAGS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + + +pushd ${BASH_SOURCE%/*} + +if [[ $1 == "clean" || $2 == "clean" ]]; then + rm -rf results +fi + +./framework.sh ${PINFLAGS} SHA2_2_192 +./framework.sh ${PINFLAGS} SHAKE_2_256 + +if [[ $1 == "test" || $2 == "test" ]]; then + popd + exit 0 +fi + +./framework.sh ${PINFLAGS} SHA2_10_192 +./framework.sh ${PINFLAGS} SHAKE_10_256 + +popd diff --git a/cryptolib/botan/algo_xmss/framework.sh b/cryptolib/botan/algo_xmss/framework.sh new file mode 100755 index 00000000..f0f727e1 --- /dev/null +++ b/cryptolib/botan/algo_xmss/framework.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=botan + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=200 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/xmss + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + : +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + ${BINARY} ${ALGO} keygen $1 + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} ${ALGO} sign $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + SHIFT=$((SHIFT)) + + WORKDIR="xmss-$ALGO" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/botan/algo_xmss/xmss.cpp b/cryptolib/botan/algo_xmss/xmss.cpp new file mode 100644 index 00000000..c49eb341 --- /dev/null +++ b/cryptolib/botan/algo_xmss/xmss.cpp @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include + +vector modes = { + "SHAKE_2_256", + "SHAKE_10_256", + "SHA2_2_192", + "SHA2_10_192", +}; + +vector operations = { + "keygen", + "sign" +}; + +int main(int argc, char* argv[]) { + Botan::AutoSeeded_RNG rng; + + if (argc != 4) { + cout << "Usage:\n\n" + << " kyber \n\n" + << " ..... asymmetric cipher mode\n" + << " ..... operation to execute, e.g. keygen or kem\n" + << " ... kyber key file, read as text\n" + << endl; + cout << "List of available modes:" << endl; + for(vector::size_type i = 0; i != modes.size(); i++) { + cout << " " << modes[i] << endl; + } + cout << endl; + cout << "List of available operations:" << endl; + for(vector::size_type i = 0; i != operations.size(); i++) { + cout << " " << operations[i] << endl; + } + cout << endl; + return (1); + } + + string str_mode (argv[1]); + string str_operation (argv[2]); + string str_keyfile (argv[3]); + + std::string mode_buffer("XMSS-"); + mode_buffer.append(str_mode); + const auto xmss_algo = Botan::XMSS_Parameters::xmss_id_from_string(mode_buffer); + + std::string keyfile_buffer_sk(str_keyfile); + + if (str_operation == "keygen") { + // Alice KeyGen + const Botan::XMSS_PrivateKey priv_key(xmss_algo, rng); + const auto priv_key_bits = priv_key.private_key_bits(); + + // Store key pair + ofstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + keyfile_sk << Botan::hex_encode(priv_key_bits); + keyfile_sk.close(); + } else if (str_operation == "sign") { + std::vector signature; + auto message = Botan::hex_decode("deadbeef"); + + // Load key pair + string line_sk; + ifstream keyfile_sk; + keyfile_sk.open(keyfile_buffer_sk); + getline(keyfile_sk, line_sk); + keyfile_sk.close(); + Botan::secure_vector priv_key_bits = + Botan::hex_decode_locked(line_sk); + + Botan::XMSS_PrivateKey priv_key(priv_key_bits); + + Botan::PK_Signer sig(priv_key, rng, str_mode); + signature = sig.sign_message(message, rng); + + Botan::PK_Verifier ver(priv_key, ""); + ver.update(message); + assert(ver.check_signature(signature)); + } else { + cout << str_operation << " is no valid operation!" << endl; + assert(false); + } + + return (0); +} + diff --git a/cryptolib/botan/botan b/cryptolib/botan/botan new file mode 160000 index 00000000..c86f835c --- /dev/null +++ b/cryptolib/botan/botan @@ -0,0 +1 @@ +Subproject commit c86f835c9aa8ac3ad7d84c6f5b175c81d6bf7bf9