-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
bin/ | ||
results/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/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 | ||
######################################################################### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#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/kyber.h> | ||
#include <botan/oids.h> | ||
#include <botan/pubkey.h> | ||
|
||
vector<string> modes = { | ||
"512", | ||
"512-90s", | ||
"768", | ||
"768-90s", | ||
"1024", | ||
"1024-90s" | ||
}; | ||
|
||
vector<string> 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<uint8_t> &cipher_text, | ||
Botan::secure_vector<uint8_t> &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<uint8_t> &cipher_text, | ||
Botan::secure_vector<uint8_t> &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 <mode> <operation> <infile> <outfile> <kyberkeyfile>\n\n" | ||
<< " <mode> ..... asymmetric cipher mode\n" | ||
<< " <operation> ..... operation to execute, e.g. keygen or kem\n" | ||
<< " <kyberkeyfile> ... kyber key file, read as text\n" | ||
// << " <symkeyfile> ..... symmetric 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_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<uint8_t> 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<uint8_t> 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); | ||
} | ||
|