Skip to content

Commit

Permalink
cryptolib/botan: Add XMSS scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
aewag committed Mar 13, 2023
1 parent 7d62132 commit 59ebb19
Show file tree
Hide file tree
Showing 6 changed files with 361 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cryptolib/botan/algo_xmss/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin/
results/
8 changes: 8 additions & 0 deletions cryptolib/botan/algo_xmss/Makefile
Original file line number Diff line number Diff line change
@@ -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/
93 changes: 93 additions & 0 deletions cryptolib/botan/algo_xmss/botan_xmss.patch
Original file line number Diff line number Diff line change
@@ -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<const uint8_t> 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,
26 changes: 26 additions & 0 deletions cryptolib/botan/algo_xmss/data_run.sh
Original file line number Diff line number Diff line change
@@ -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
133 changes: 133 additions & 0 deletions cryptolib/botan/algo_xmss/framework.sh
Original file line number Diff line number Diff line change
@@ -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 <main> Start recording at function <main>. Note that the <main>
# 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
#########################################################################
99 changes: 99 additions & 0 deletions cryptolib/botan/algo_xmss/xmss.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <cassert>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#include <botan/block_cipher.h>
#include <botan/auto_rng.h>
#include <botan/rng.h>
#include <botan/hex.h>
#include <botan/xmss.h>
#include <botan/oids.h>
#include <botan/pubkey.h>

vector<string> modes = {
"SHAKE_2_256",
"SHAKE_10_256",
"SHA2_2_192",
"SHA2_10_192",
};

vector<string> operations = {
"keygen",
"sign"
};

int main(int argc, char* argv[]) {
Botan::AutoSeeded_RNG rng;

if (argc != 4) {
cout << "Usage:\n\n"
<< " kyber <mode> <operation> <keyfile>\n\n"
<< " <mode> ..... asymmetric cipher mode\n"
<< " <operation> ..... operation to execute, e.g. keygen or kem\n"
<< " <keyfile> ... kyber key file, read as text\n"
<< endl;
cout << "List of available modes:" << endl;
for(vector<string>::size_type i = 0; i != modes.size(); i++) {
cout << " " << modes[i] << endl;
}
cout << endl;
cout << "List of available operations:" << endl;
for(vector<string>::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<uint8_t> 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<uint8_t> 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);
}

0 comments on commit 59ebb19

Please sign in to comment.