Skip to content

Commit 0ae9441

Browse files
committed
cryptolib/botan: Add XMSS scripts
1 parent 1ad2f05 commit 0ae9441

File tree

6 files changed

+361
-0
lines changed

6 files changed

+361
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
bin/
2+
results/

cryptolib/botan/algo_xmss/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
all: xmss
2+
3+
xmss: xmss.cpp
4+
mkdir -p bin
5+
g++-11 -std=c++20 -g -O3 -Wall -I ../botan/build/include -Wl,-rpath=../botan/ $^ -o bin/$@ -L ../botan/ -l:libbotan-3.a
6+
7+
clean:
8+
rm -rf bin/
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
diff --git a/src/lib/pubkey/xmss/xmss_hash.cpp b/src/lib/pubkey/xmss/xmss_hash.cpp
2+
index 957e9e989..f14c3a305 100644
3+
--- a/src/lib/pubkey/xmss/xmss_hash.cpp
4+
+++ b/src/lib/pubkey/xmss/xmss_hash.cpp
5+
@@ -40,8 +40,8 @@ void XMSS_Hash::h_msg_init(std::span<const uint8_t> randomness,
6+
m_msg_hash->clear();
7+
m_msg_hash->update(m_zero_padding);
8+
m_msg_hash->update(0x02);
9+
- m_msg_hash->update(randomness.data(), randomness.size());
10+
- m_msg_hash->update(root.data(), root.size());
11+
+ // m_msg_hash->update(randomness.data(), randomness.size());
12+
+ // m_msg_hash->update(root.data(), root.size());
13+
m_msg_hash->update(index_bytes.data(), index_bytes.size());
14+
}
15+
16+
diff --git a/src/lib/pubkey/xmss/xmss_parameters.cpp b/src/lib/pubkey/xmss/xmss_parameters.cpp
17+
index b53f6eaed..d5c0790e4 100644
18+
--- a/src/lib/pubkey/xmss/xmss_parameters.cpp
19+
+++ b/src/lib/pubkey/xmss/xmss_parameters.cpp
20+
@@ -30,6 +30,8 @@ XMSS_Parameters::xmss_algorithm_t XMSS_Parameters::xmss_id_from_string(const std
21+
{ return XMSS_SHA2_16_512; }
22+
if(param_set == "XMSS-SHA2_20_512")
23+
{ return XMSS_SHA2_20_512; }
24+
+ if(param_set == "XMSS-SHAKE_2_256")
25+
+ { return XMSS_SHAKE_2_256; }
26+
if(param_set == "XMSS-SHAKE_10_256")
27+
{ return XMSS_SHAKE_10_256; }
28+
if(param_set == "XMSS-SHAKE_16_256")
29+
@@ -42,6 +44,8 @@ XMSS_Parameters::xmss_algorithm_t XMSS_Parameters::xmss_id_from_string(const std
30+
{ return XMSS_SHAKE_16_512; }
31+
if(param_set == "XMSS-SHAKE_20_512")
32+
{ return XMSS_SHAKE_20_512; }
33+
+ if(param_set == "XMSS-SHA2_2_192")
34+
+ { return XMSS_SHA2_2_192; }
35+
if(param_set == "XMSS-SHA2_10_192")
36+
{ return XMSS_SHA2_10_192; }
37+
if(param_set == "XMSS-SHA2_16_192")
38+
@@ -139,6 +143,17 @@ XMSS_Parameters::XMSS_Parameters(xmss_algorithm_t oid)
39+
m_strength = 512;
40+
m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHA2_512;
41+
break;
42+
+ case XMSS_SHAKE_2_256:
43+
+ m_element_size = 32;
44+
+ m_hash_id_size = 32;
45+
+ m_w = 16;
46+
+ m_len = 67;
47+
+ m_tree_height = 2;
48+
+ m_name = "XMSS-SHAKE_2_256";
49+
+ m_hash_name = "SHAKE-128(256)";
50+
+ m_strength = 256;
51+
+ m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHAKE_256;
52+
+ break;
53+
case XMSS_SHAKE_10_256:
54+
m_element_size = 32;
55+
m_hash_id_size = 32;
56+
@@ -205,6 +220,17 @@ XMSS_Parameters::XMSS_Parameters(xmss_algorithm_t oid)
57+
m_strength = 512;
58+
m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHAKE_512;
59+
break;
60+
+ case XMSS_SHA2_2_192:
61+
+ m_element_size = 24;
62+
+ m_hash_id_size = 4;
63+
+ m_w = 16;
64+
+ m_len = 51;
65+
+ m_tree_height = 2;
66+
+ m_name = "XMSS-SHA2_2_192";
67+
+ m_hash_name = "Truncated(SHA-256,192)";
68+
+ m_strength = 192;
69+
+ m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHA2_192;
70+
+ break;
71+
case XMSS_SHA2_10_192:
72+
m_element_size = 24;
73+
m_hash_id_size = 4;
74+
diff --git a/src/lib/pubkey/xmss/xmss_parameters.h b/src/lib/pubkey/xmss/xmss_parameters.h
75+
index 27564390a..f1275f57f 100644
76+
--- a/src/lib/pubkey/xmss/xmss_parameters.h
77+
+++ b/src/lib/pubkey/xmss/xmss_parameters.h
78+
@@ -149,6 +149,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_Parameters
79+
XMSS_SHA2_10_512 = 0x00000004,
80+
XMSS_SHA2_16_512 = 0x00000005,
81+
XMSS_SHA2_20_512 = 0x00000006,
82+
+ XMSS_SHAKE_2_256 = 0x000000f7,
83+
XMSS_SHAKE_10_256 = 0x00000007,
84+
XMSS_SHAKE_16_256 = 0x00000008,
85+
XMSS_SHAKE_20_256 = 0x00000009,
86+
@@ -157,6 +158,7 @@ class BOTAN_PUBLIC_API(2,0) XMSS_Parameters
87+
XMSS_SHAKE_20_512 = 0x0000000c,
88+
89+
// from NIST SP.800-208
90+
+ XMSS_SHA2_2_192 = 0x000000fd,
91+
XMSS_SHA2_10_192 = 0x0000000d,
92+
XMSS_SHA2_16_192 = 0x0000000e,
93+
XMSS_SHA2_20_192 = 0x0000000f,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
PINFLAGS="--phase1 --phase2 --export --parallel"
6+
export RESULTDIR=results
7+
8+
9+
pushd ${BASH_SOURCE%/*}
10+
11+
if [[ $1 == "clean" || $2 == "clean" ]]; then
12+
rm -rf results
13+
fi
14+
15+
./framework.sh ${PINFLAGS} SHA2_2_192
16+
./framework.sh ${PINFLAGS} SHAKE_2_256
17+
18+
if [[ $1 == "test" || $2 == "test" ]]; then
19+
popd
20+
exit 0
21+
fi
22+
23+
./framework.sh ${PINFLAGS} SHA2_10_192
24+
./framework.sh ${PINFLAGS} SHAKE_10_256
25+
26+
popd
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/bin/bash
2+
3+
#########################################################################
4+
# DO NOT CHANGE: Preparing DATA
5+
#------------------------------------------------------------------------
6+
source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; }
7+
#########################################################################
8+
9+
#------------------------------------------------------------------------
10+
# Specify your framework settings used by DATA
11+
#------------------------------------------------------------------------
12+
13+
# The name of the framework. Do not use spaces or special characters.
14+
export FRAMEWORK=botan
15+
16+
# The file containing all supported algorithms
17+
export TARGETFILE=targets.txt
18+
19+
# The number of measurements for difference detection (phase1)
20+
export PHASE1_TRACES=3
21+
22+
# The number of constant keys for generic tests (phase2)
23+
# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES
24+
export PHASE2_FIXEDKEYS=3
25+
26+
# The number of measurements per constant key for generic tests (phase2)
27+
export PHASE2_TRACES=100
28+
29+
# The number of measurements for specific tests (phase3)
30+
export PHASE3_TRACES=200
31+
32+
# (Optional) Additional flags for the pintool. Supported flags are:
33+
# -main <main> Start recording at function <main>. Note that the <main>
34+
# symbol must exist, otherwise this will yield empty traces!
35+
# -heap Trace heap allocations and replace heap addresses with
36+
# relative offset
37+
export PINTOOL_ARGS="-heap"
38+
39+
#------------------------------------------------------------------------
40+
# Implement your framework-specific callbacks
41+
#------------------------------------------------------------------------
42+
#
43+
# Globally available environment variables:
44+
# $FRAMEWORK The framework name
45+
# $BASEDIR The absolute directory path of this script
46+
# $DATA_COMMON The absolute directory for common DATA scripts
47+
# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models
48+
#
49+
# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run
50+
# $ALGO The currently tested algo
51+
#
52+
# Available for cb_pre_run, cb_run_command, cb_post_run
53+
# $ENVFILE
54+
55+
export BINARY=${PWD}/bin/xmss
56+
57+
# The leakage model of phase 3.
58+
# See ${DATA_LEAKAGE_MODELS} for all options.
59+
export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/rsa_privkey_hw.py
60+
61+
# DATA callback for setting up the framework to analyze. This callback
62+
# is invoked once inside the current directory before analysis starts.
63+
# Implement framework-specific tasks here like framework compilation.
64+
function cb_prepare_framework {
65+
:
66+
}
67+
68+
# DATA callback for generating keys. This callback is invoked every
69+
# time a new key is needed. Implement key generation according to
70+
# your algorithm and store the generated key inside a file named $2.
71+
#
72+
# $1 ... key file name
73+
function cb_genkey {
74+
${BINARY} ${ALGO} keygen $1
75+
RES=$((RES + $?))
76+
}
77+
78+
# DATA callback for custom commands that are executed immediately before
79+
# the algorithm is profiled. It is executed in a temporary directory
80+
# which contains the keyfile $1 and ${ENVFILE}.
81+
#
82+
# If 'cb_run_command' needs any other files, copy them to ${PWD}.
83+
#
84+
# $1 ... key file name
85+
function cb_pre_run {
86+
log_verbose "running with key $1"
87+
}
88+
89+
# DATA callback for the main invocation of the tested algorithm.
90+
# It shall return the bash command to execute as string. It is
91+
# executed inside a temporary directory with a clean environment.
92+
# If you need special files or environment variables set, specify
93+
# them in cb_pre_run.
94+
#
95+
# $1 ... key file name
96+
function cb_run_command {
97+
echo "${BINARY} ${ALGO} sign $1"
98+
}
99+
100+
# DATA callback for custom commands that are executed immediately after
101+
# the algorithm is profiled. It is executed in a temporary directory.
102+
# You can cleanup any custom files generated by your algorithm.
103+
#
104+
# $1 ... key file name
105+
function cb_post_run {
106+
:
107+
}
108+
109+
# DATA callback for preparing an individual algorithm. It shall:
110+
# 1. Parse the next algorithm from the commandline string of all algorithms
111+
# and set up anything necessary for analyzing this algorithm.
112+
# If the algorithm needs additional parameters (like key sizes),
113+
# increase $SHIFT accordingly.
114+
# 2. Configure $WORKDIR, which will create a subdirectory holding all
115+
# intermediate files generated by the algorithm and the results.
116+
# Do not use an absolute path!
117+
#
118+
# $* ... algorithm string from the commandline
119+
function cb_prepare_algo {
120+
ALGO=$1
121+
# key bits
122+
SHIFT=$((SHIFT))
123+
124+
WORKDIR="xmss-$ALGO"
125+
}
126+
127+
#########################################################################
128+
# DO NOT CHANGE: Running DATA's commandline parser
129+
#------------------------------------------------------------------------
130+
DATA_parse "$@"
131+
#------------------------------------------------------------------------
132+
# DO NOT ADD CODE AFTER THIS LINE
133+
#########################################################################

cryptolib/botan/algo_xmss/xmss.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#include <cassert>
2+
#include <fstream>
3+
#include <iostream>
4+
#include <string>
5+
#include <vector>
6+
using namespace std;
7+
8+
#include <botan/block_cipher.h>
9+
#include <botan/auto_rng.h>
10+
#include <botan/rng.h>
11+
#include <botan/hex.h>
12+
#include <botan/xmss.h>
13+
#include <botan/oids.h>
14+
#include <botan/pubkey.h>
15+
16+
vector<string> modes = {
17+
"SHAKE_2_256",
18+
"SHAKE_10_256",
19+
"SHA2_2_192",
20+
"SHA2_10_192",
21+
};
22+
23+
vector<string> operations = {
24+
"keygen",
25+
"sign"
26+
};
27+
28+
int main(int argc, char* argv[]) {
29+
Botan::AutoSeeded_RNG rng;
30+
31+
if (argc != 4) {
32+
cout << "Usage:\n\n"
33+
<< " kyber <mode> <operation> <keyfile>\n\n"
34+
<< " <mode> ..... asymmetric cipher mode\n"
35+
<< " <operation> ..... operation to execute, e.g. keygen or kem\n"
36+
<< " <keyfile> ... kyber key file, read as text\n"
37+
<< endl;
38+
cout << "List of available modes:" << endl;
39+
for(vector<string>::size_type i = 0; i != modes.size(); i++) {
40+
cout << " " << modes[i] << endl;
41+
}
42+
cout << endl;
43+
cout << "List of available operations:" << endl;
44+
for(vector<string>::size_type i = 0; i != operations.size(); i++) {
45+
cout << " " << operations[i] << endl;
46+
}
47+
cout << endl;
48+
return (1);
49+
}
50+
51+
string str_mode (argv[1]);
52+
string str_operation (argv[2]);
53+
string str_keyfile (argv[3]);
54+
55+
std::string mode_buffer("XMSS-");
56+
mode_buffer.append(str_mode);
57+
const auto xmss_algo = Botan::XMSS_Parameters::xmss_id_from_string(mode_buffer);
58+
59+
std::string keyfile_buffer_sk(str_keyfile);
60+
61+
if (str_operation == "keygen") {
62+
// Alice KeyGen
63+
const Botan::XMSS_PrivateKey priv_key(xmss_algo, rng);
64+
const auto priv_key_bits = priv_key.private_key_bits();
65+
66+
// Store key pair
67+
ofstream keyfile_sk;
68+
keyfile_sk.open(keyfile_buffer_sk);
69+
keyfile_sk << Botan::hex_encode(priv_key_bits);
70+
keyfile_sk.close();
71+
} else if (str_operation == "sign") {
72+
std::vector<uint8_t> signature;
73+
auto message = Botan::hex_decode("deadbeef");
74+
75+
// Load key pair
76+
string line_sk;
77+
ifstream keyfile_sk;
78+
keyfile_sk.open(keyfile_buffer_sk);
79+
getline(keyfile_sk, line_sk);
80+
keyfile_sk.close();
81+
Botan::secure_vector<uint8_t> priv_key_bits =
82+
Botan::hex_decode_locked(line_sk);
83+
84+
Botan::XMSS_PrivateKey priv_key(priv_key_bits);
85+
86+
Botan::PK_Signer sig(priv_key, rng, str_mode);
87+
signature = sig.sign_message(message, rng);
88+
89+
Botan::PK_Verifier ver(priv_key, "");
90+
ver.update(message);
91+
assert(ver.check_signature(signature));
92+
} else {
93+
cout << str_operation << " is no valid operation!" << endl;
94+
assert(false);
95+
}
96+
97+
return (0);
98+
}
99+

0 commit comments

Comments
 (0)