diff --git a/.gitignore b/.gitignore index 9bfd15b..f6ea97f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Build artifacts -/build/ +/build*/ CMakeFiles/ CMakeCache.txt cmake_install.cmake @@ -55,3 +55,6 @@ __pycache__/ *~ .DS_Store Thumbs.db + +#Environment files +.env diff --git a/CMakeLists.txt b/CMakeLists.txt index de9201e..00d9bf8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,4 +7,10 @@ if(BUILD_TESTING) include(CTest) endif() -add_subdirectory(third_party) \ No newline at end of file +add_subdirectory(third_party) +add_subdirectory(src) +add_subdirectory(bench) + +if(BUILD_TESTING) + add_subdirectory(tests) +endif() \ No newline at end of file diff --git a/README.md b/README.md index 8c7e7a6..99630c9 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,32 @@ git submodule update --init --recursive ./build/bench/bench_batch --algo hypericum --batch-size 16 --iterations 100 ``` +### Paramset Selection + +Both Hypericum and Kryzhovnik support build-time paramset selection via CMake. + +```bash +cmake -S . -B build \ + -DHYPERICUM_PARAMSET=m_128_20 \ + -DKRYZHOVNIK_PARAMSET=medium +cmake --build build --parallel +``` + +Supported Kryzhovnik values: `small`, `medium`, `large`, `debug`. + +`debug` is intended for fast diagnostics and troubleshooting, not security evaluation. + +The benchmark helper script also supports separate flags: + +```bash +./scripts/benchmark.sh \ + --algo kryzhovnik \ + --kryzhovnik-params small \ + --hypericum-params m_128_20 +``` + +Note: Kryzhovnik constants are aligned with `security.sage` for `small/medium/large`. Keep validating against the official specification before production use. + ### Expected Output (after MVP) After running benchmarks, the `results/` directory will contain: diff --git a/README_ru.md b/README_ru.md index 0bbb3ea..ecc2cb8 100644 --- a/README_ru.md +++ b/README_ru.md @@ -89,6 +89,32 @@ git submodule update --init --recursive ./build/bench/bench_batch --algo hypericum --batch-size 16 --iterations 100 ``` +### Выбор paramset + +Для Hypericum и Kryzhovnik поддерживается выбор набора параметров на этапе сборки через CMake. + +```bash +cmake -S . -B build \ + -DHYPERICUM_PARAMSET=m_128_20 \ + -DKRYZHOVNIK_PARAMSET=medium +cmake --build build --parallel +``` + +Поддерживаемые значения для Kryzhovnik: `small`, `medium`, `large`, `debug`. + +`debug` предназначен для быстрой диагностики и отладки, а не для оценки стойкости. + +В benchmark-скрипте можно задавать наборы отдельно: + +```bash +./scripts/benchmark.sh \ + --algo kryzhovnik \ + --kryzhovnik-params small \ + --hypericum-params m_128_20 +``` + +Примечание: константы Kryzhovnik для `small/medium/large` синхронизированы со скриптом `security.sage`; перед production-использованием их нужно дополнительно верифицировать по официальной спецификации. + ### Ожидаемые результаты (после MVP) После запуска бенчмарков в директории `results/` появятся: diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt new file mode 100644 index 0000000..51d7000 --- /dev/null +++ b/bench/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(bench_seq bench_seq.c) + +target_link_libraries(bench_seq PRIVATE batch_bench_adapters) + +target_compile_features(bench_seq PRIVATE c_std_99) diff --git a/bench/bench_seq.c b/bench/bench_seq.c new file mode 100644 index 0000000..354b6b7 --- /dev/null +++ b/bench/bench_seq.c @@ -0,0 +1,452 @@ +#include "batch_bench.h" +#include "utils/message_gen.h" +#include "utils/timer.h" + +#include +#include +#include +#include +#include + +typedef struct bench_config { + const char *algo; + const char *params; + size_t batch_size; + size_t iters; + size_t msg_size; + uint64_t seed; + int verify; + const char *out_csv; + const char *out_json; +} bench_config; + +typedef struct bench_result { + const char *algorithm; + const char *params; + size_t batch_size; + double keygen_ms; + double time_seq_ms; + double verify_ms; + double serialize_time_ms; + double peak_memory_mb; + double total_sig_size_mb; +} bench_result; + +static void print_usage(const char *prog) { + printf("Usage: %s [options]\n", prog); + printf(" --algo Algorithm name or all (default: all)\n"); + printf(" --params Paramset tag for result output (default: default)\n"); + printf(" --batch-size Messages per iteration (default: 1)\n"); + printf(" --iters Iterations (default: 100)\n"); + printf(" --msg-size Message size in bytes (default: 1024)\n"); + printf(" --seed Deterministic message seed (default: 1)\n"); + printf(" --verify <0|1> Run verify pass (default: 1)\n"); + printf(" --out-csv Output CSV path\n"); + printf(" --out-json Output JSON path\n"); + printf(" --help Show this message\n"); +} + +static int parse_size(const char *s, size_t *out) { + char *end = NULL; + unsigned long long v; + + if (s == NULL || out == NULL) { + return -1; + } + errno = 0; + v = strtoull(s, &end, 10); + if (errno != 0 || end == s || *end != '\0') { + return -1; + } + *out = (size_t)v; + return 0; +} + +static int parse_u64(const char *s, uint64_t *out) { + char *end = NULL; + unsigned long long v; + + if (s == NULL || out == NULL) { + return -1; + } + errno = 0; + v = strtoull(s, &end, 10); + if (errno != 0 || end == s || *end != '\0') { + return -1; + } + *out = (uint64_t)v; + return 0; +} + +static int parse_int(const char *s, int *out) { + char *end = NULL; + long v; + + if (s == NULL || out == NULL) { + return -1; + } + errno = 0; + v = strtol(s, &end, 10); + if (errno != 0 || end == s || *end != '\0') { + return -1; + } + *out = (int)v; + return 0; +} + +static int parse_args(int argc, char **argv, bench_config *cfg) { + int i; + + cfg->algo = "all"; + cfg->params = "default"; + cfg->batch_size = 1; + cfg->iters = 100; + cfg->msg_size = BB_DEFAULT_MESSAGE_SIZE; + cfg->seed = 1; + cfg->verify = 1; + cfg->out_csv = NULL; + cfg->out_json = NULL; + + for (i = 1; i < argc; ++i) { + const char *arg = argv[i]; + if (strcmp(arg, "--help") == 0) { + print_usage(argv[0]); + return 1; + } + if (strcmp(arg, "--algo") == 0 && i + 1 < argc) { + cfg->algo = argv[++i]; + continue; + } + if (strcmp(arg, "--params") == 0 && i + 1 < argc) { + cfg->params = argv[++i]; + continue; + } + if (strcmp(arg, "--batch-size") == 0 && i + 1 < argc) { + if (parse_size(argv[++i], &cfg->batch_size) != 0 || cfg->batch_size == 0) { + return -1; + } + continue; + } + if (strcmp(arg, "--iters") == 0 && i + 1 < argc) { + if (parse_size(argv[++i], &cfg->iters) != 0 || cfg->iters == 0) { + return -1; + } + continue; + } + if (strcmp(arg, "--msg-size") == 0 && i + 1 < argc) { + if (parse_size(argv[++i], &cfg->msg_size) != 0 || cfg->msg_size == 0) { + return -1; + } + continue; + } + if (strcmp(arg, "--seed") == 0 && i + 1 < argc) { + if (parse_u64(argv[++i], &cfg->seed) != 0) { + return -1; + } + continue; + } + if (strcmp(arg, "--verify") == 0 && i + 1 < argc) { + if (parse_int(argv[++i], &cfg->verify) != 0 || (cfg->verify != 0 && cfg->verify != 1)) { + return -1; + } + continue; + } + if (strcmp(arg, "--out-csv") == 0 && i + 1 < argc) { + cfg->out_csv = argv[++i]; + continue; + } + if (strcmp(arg, "--out-json") == 0 && i + 1 < argc) { + cfg->out_json = argv[++i]; + continue; + } + return -1; + } + + return 0; +} + +static double get_peak_memory_mb(void) { + struct rusage ru; + if (getrusage(RUSAGE_SELF, &ru) != 0) { + return 0.0; + } + return (double)ru.ru_maxrss / 1024.0; +} + +static int run_one(const bb_algorithm *algo, const bench_config *cfg, bench_result *out) { + uint8_t *sk = NULL; + uint8_t *pk = NULL; + uint8_t *msg = NULL; + uint8_t *sigs = NULL; + size_t *sig_lens = NULL; + uint8_t *serialized = NULL; + size_t sk_len = 0; + size_t pk_len = 0; + size_t total_sig_bytes = 0; + size_t it; + bb_timer timer; + + sk = (uint8_t *)malloc(algo->secret_key_bytes); + pk = (uint8_t *)malloc(algo->public_key_bytes); + msg = (uint8_t *)malloc(cfg->msg_size); + sigs = (uint8_t *)malloc(cfg->batch_size * algo->signature_bytes); + sig_lens = (size_t *)calloc(cfg->batch_size, sizeof(size_t)); + if (sk == NULL || pk == NULL || msg == NULL || sigs == NULL || sig_lens == NULL) { + goto fail; + } + + bb_timer_start(&timer); + if (algo->keygen(sk, algo->secret_key_bytes, &sk_len, + pk, algo->public_key_bytes, &pk_len) != BB_OK) { + goto fail; + } + bb_timer_stop(&timer); + out->keygen_ms = bb_timer_elapsed_ms(&timer); + + out->time_seq_ms = 0.0; + out->verify_ms = 0.0; + out->serialize_time_ms = 0.0; + + for (it = 0; it < cfg->iters; ++it) { + size_t i; + + for (i = 0; i < cfg->batch_size; ++i) { + size_t sig_len = 0; + uint8_t *sig_slot = sigs + (i * algo->signature_bytes); + + bb_fill_message(msg, cfg->msg_size, cfg->seed, it * cfg->batch_size + i); + + bb_timer_start(&timer); + if (algo->sign(sk, sk_len, pk, pk_len, + msg, cfg->msg_size, + sig_slot, algo->signature_bytes, + &sig_len) != BB_OK) { + goto fail; + } + bb_timer_stop(&timer); + out->time_seq_ms += bb_timer_elapsed_ms(&timer); + + sig_lens[i] = sig_len; + total_sig_bytes += sig_len; + + if (cfg->verify) { + bb_timer_start(&timer); + if (algo->verify(pk, pk_len, msg, cfg->msg_size, + sig_slot, sig_len) != BB_OK) { + goto fail; + } + bb_timer_stop(&timer); + out->verify_ms += bb_timer_elapsed_ms(&timer); + } + } + + serialized = (uint8_t *)realloc(serialized, total_sig_bytes == 0 ? 1 : total_sig_bytes); + if (serialized == NULL) { + goto fail; + } + + { + size_t cursor = 0; + bb_timer_start(&timer); + for (i = 0; i < cfg->batch_size; ++i) { + memcpy(serialized + cursor, + sigs + (i * algo->signature_bytes), + sig_lens[i]); + cursor += sig_lens[i]; + } + bb_timer_stop(&timer); + out->serialize_time_ms += bb_timer_elapsed_ms(&timer); + } + } + + out->algorithm = algo->name; + out->params = cfg->params; + out->batch_size = cfg->batch_size; + out->peak_memory_mb = get_peak_memory_mb(); + out->total_sig_size_mb = (double)total_sig_bytes / (1024.0 * 1024.0); + + free(sk); + free(pk); + free(msg); + free(sigs); + free(sig_lens); + free(serialized); + return 0; + +fail: + free(sk); + free(pk); + free(msg); + free(sigs); + free(sig_lens); + free(serialized); + return -1; +} + +static void print_result(const bench_result *r) { + printf("algo=%s params=%s batch=%zu keygen_ms=%.3f seq_ms=%.3f verify_ms=%.3f serialize_ms=%.3f peak_mem_mb=%.2f total_sig_mb=%.3f\n", + r->algorithm, + r->params, + r->batch_size, + r->keygen_ms, + r->time_seq_ms, + r->verify_ms, + r->serialize_time_ms, + r->peak_memory_mb, + r->total_sig_size_mb); +} + +static int write_csv(FILE *f, const bench_result *r) { + return fprintf( + f, + "%s,%s,%zu,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f\n", + r->algorithm, + r->params, + r->batch_size, + r->time_seq_ms, + 0.0, + 0.0, + r->peak_memory_mb, + r->total_sig_size_mb, + r->serialize_time_ms) < 0 + ? -1 + : 0; +} + +static int write_json(FILE *f, const bench_result *results, size_t count, + const bench_config *cfg) { + size_t i; + if (fprintf(f, + "{\n" + " \"config\": {\n" + " \"algo\": \"%s\",\n" + " \"params\": \"%s\",\n" + " \"batch_size\": %zu,\n" + " \"iters\": %zu,\n" + " \"msg_size\": %zu,\n" + " \"seed\": %llu,\n" + " \"verify\": %d\n" + " },\n" + " \"results\": [\n", + cfg->algo, + cfg->params, + cfg->batch_size, + cfg->iters, + cfg->msg_size, + (unsigned long long)cfg->seed, + cfg->verify) < 0) { + return -1; + } + + for (i = 0; i < count; ++i) { + const bench_result *r = &results[i]; + if (fprintf(f, + " {\"algorithm\":\"%s\",\"params\":\"%s\",\"batch_size\":%zu," + "\"time_seq_ms\":%.6f,\"time_batch_ms\":%.6f," + "\"speedup\":%.6f,\"peak_memory_MB\":%.6f," + "\"total_sig_size_MB\":%.6f,\"serialize_time_ms\":%.6f}%s\n", + r->algorithm, + r->params, + r->batch_size, + r->time_seq_ms, + 0.0, + 0.0, + r->peak_memory_mb, + r->total_sig_size_mb, + r->serialize_time_ms, + i + 1 == count ? "" : ",") < 0) { + return -1; + } + } + + return fprintf(f, " ]\n}\n") < 0 ? -1 : 0; +} + +int main(int argc, char **argv) { + bench_config cfg; + bench_result *results = NULL; + size_t results_count = 0; + FILE *csv = NULL; + FILE *json = NULL; + size_t i; + int parse_rc; + + parse_rc = parse_args(argc, argv, &cfg); + if (parse_rc == 1) { + return 0; + } + if (parse_rc != 0) { + print_usage(argv[0]); + return 1; + } + + results = (bench_result *)calloc(bb_algorithm_count(), sizeof(bench_result)); + if (results == NULL) { + return 1; + } + + if (cfg.out_csv != NULL) { + csv = fopen(cfg.out_csv, "w"); + if (csv == NULL) { + free(results); + return 1; + } + fprintf(csv, + "algorithm,params,batch_size,time_seq_ms,time_batch_ms,speedup," + "peak_memory_MB,total_sig_size_MB,serialize_time_ms\n"); + } + + for (i = 0; i < bb_algorithm_count(); ++i) { + const bb_algorithm *algo = bb_algorithm_at(i); + + if (strcmp(cfg.algo, "all") != 0 && strcmp(cfg.algo, algo->name) != 0) { + continue; + } + + if (run_one(algo, &cfg, &results[results_count]) != 0) { + if (csv != NULL) { + fclose(csv); + } + free(results); + return 1; + } + + print_result(&results[results_count]); + if (csv != NULL && write_csv(csv, &results[results_count]) != 0) { + fclose(csv); + free(results); + return 1; + } + + ++results_count; + } + + if (results_count == 0) { + if (csv != NULL) { + fclose(csv); + } + free(results); + return 1; + } + + if (csv != NULL) { + fclose(csv); + } + + if (cfg.out_json != NULL) { + json = fopen(cfg.out_json, "w"); + if (json == NULL) { + free(results); + return 1; + } + if (write_json(json, results, results_count, &cfg) != 0) { + fclose(json); + free(results); + return 1; + } + fclose(json); + } + + free(results); + return 0; +} diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh new file mode 100755 index 0000000..33e2355 --- /dev/null +++ b/scripts/benchmark.sh @@ -0,0 +1,203 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BUILD_DIR="${ROOT_DIR}/build" +OUTPUT_DIR="${ROOT_DIR}/results/bench-$(date +%Y%m%d-%H%M%S)" +ALGOS="all" +HYPERICUM_PARAMS="m_128_20" +KRYZHOVNIK_PARAMS="medium" +BATCH_SIZES="1,2,4,8,16,32,64" +ITERS=100 +MSG_SIZE=1024 +SEED=1 +VERIFY=1 +DRY_RUN=0 +SKIP_EXISTING=1 + +usage() { + cat < + --hypericum-params (default: m_128_20) + --kryzhovnik-params (default: medium) + --params (legacy: sets hypericum; + also sets kryzhovnik when value is small|medium|large) + + --batch-sizes (default: 1,2,4,8,16,32,64) + --iters (default: 100) + --msg-size (default: 1024) + --seed (default: 1) + --verify <0|1> (default: 1) + --build-dir (default: ./build) + --output-dir (default: ./results/bench-) + --dry-run + --skip-existing <0|1> (default: 1) +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --algo) + ALGOS="$2" + shift 2 + ;; + --batch-sizes) + BATCH_SIZES="$2" + shift 2 + ;; + --params) + HYPERICUM_PARAMS="$2" + case "$2" in + small|medium|large|debug) + KRYZHOVNIK_PARAMS="$2" + ;; + esac + shift 2 + ;; + --hypericum-params) + HYPERICUM_PARAMS="$2" + shift 2 + ;; + --kryzhovnik-params) + KRYZHOVNIK_PARAMS="$2" + shift 2 + ;; + --iters) + ITERS="$2" + shift 2 + ;; + --msg-size) + MSG_SIZE="$2" + shift 2 + ;; + --seed) + SEED="$2" + shift 2 + ;; + --verify) + VERIFY="$2" + shift 2 + ;; + --build-dir) + BUILD_DIR="$2" + shift 2 + ;; + --output-dir) + OUTPUT_DIR="$2" + shift 2 + ;; + --dry-run) + DRY_RUN=1 + shift + ;; + --skip-existing) + SKIP_EXISTING="$2" + shift 2 + ;; + --help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" + usage + exit 1 + ;; + esac +done + +mkdir -p "$OUTPUT_DIR" + +echo "[benchmark] root: $ROOT_DIR" +echo "[benchmark] build dir: $BUILD_DIR" +echo "[benchmark] output: $OUTPUT_DIR" +echo "[benchmark] hypericum: $HYPERICUM_PARAMS" +echo "[benchmark] kryzhovnik:$KRYZHOVNIK_PARAMS" +echo "[benchmark] skip: $SKIP_EXISTING" + +auto_configure_build() { + cmake -S "$ROOT_DIR" -B "$BUILD_DIR" \ + -DHYPERICUM_PARAMSET="$HYPERICUM_PARAMS" \ + -DKRYZHOVNIK_PARAMSET="$KRYZHOVNIK_PARAMS" + cmake --build "$BUILD_DIR" --parallel +} + +run_one() { + local algo="$1" + local batch_size="$2" + local csv_out="$OUTPUT_DIR/${algo}_b${batch_size}.csv" + local json_out="$OUTPUT_DIR/${algo}_b${batch_size}.json" + local csv_tmp="$csv_out.tmp" + local json_tmp="$json_out.tmp" + local params_label="default" + + case "$algo" in + hypericum) + params_label="$HYPERICUM_PARAMS" + ;; + kryzhovnik) + params_label="$KRYZHOVNIK_PARAMS" + ;; + esac + + if [[ "$SKIP_EXISTING" -eq 1 ]]; then + if [[ -s "$csv_out" && -s "$json_out" ]]; then + echo "[skip] algo=$algo batch_size=$batch_size (artifacts exist)" + return + fi + fi + + rm -f "$csv_tmp" "$json_tmp" + if [[ -f "$csv_out" && ! -s "$csv_out" ]]; then + rm -f "$csv_out" + fi + if [[ -f "$json_out" && ! -s "$json_out" ]]; then + rm -f "$json_out" + fi + + local cmd=( + "$BUILD_DIR/bench/bench_seq" + --algo "$algo" + --batch-size "$batch_size" + --iters "$ITERS" + --msg-size "$MSG_SIZE" + --seed "$SEED" + --params "$params_label" + --verify "$VERIFY" + --out-csv "$csv_tmp" + --out-json "$json_tmp" + ) + + if [[ "$DRY_RUN" -eq 1 ]]; then + echo "[dry-run] ${cmd[*]}" + else + echo "[run] algo=$algo batch_size=$batch_size" + "${cmd[@]}" + mv "$csv_tmp" "$csv_out" + mv "$json_tmp" "$json_out" + fi +} + +if [[ "$DRY_RUN" -eq 1 ]]; then + echo "[dry-run] cmake -S $ROOT_DIR -B $BUILD_DIR -DHYPERICUM_PARAMSET=$HYPERICUM_PARAMS -DKRYZHOVNIK_PARAMSET=$KRYZHOVNIK_PARAMS" + echo "[dry-run] cmake --build $BUILD_DIR --parallel" +else + auto_configure_build +fi + +IFS=',' read -r -a batches <<< "$BATCH_SIZES" + +if [[ "$ALGOS" == "all" ]]; then + for algo in shipovnik hypericum kryzhovnik; do + for b in "${batches[@]}"; do + run_one "$algo" "$b" + done + done +else + for b in "${batches[@]}"; do + run_one "$ALGOS" "$b" + done +fi + +echo "[benchmark] done" diff --git a/scripts/security.sage b/scripts/security.sage new file mode 100644 index 0000000..a4977c5 --- /dev/null +++ b/scripts/security.sage @@ -0,0 +1,286 @@ +from estimator import * + +def SVP_Classical(dim): + return 8*(dim)*(3/2)**(dim/2) + +def SVP_Quantum(dim): + return 8*(dim)*ZZ(2)**RR(0.265*dim) + + +# LWR +def LWR_estiamtes(n, l, k, q, p, s, model=SVP_Classical): + nLWE = n*l + m = k*n # m = k*n + s_bound = s + secret_distribution = (-s_bound, s_bound) + alpha = sqrt(2*pi)*1/RR(2*p) + success_probability = 0.99 + reduction_cost_model = lambda beta, d, B: model(beta) + res_primal = primal_usvp(nLWE, alpha, q, secret_distribution=secret_distribution, m=m, success_probability=success_probability, reduction_cost_model=reduction_cost_model) + res_dual = dual_scale(nLWE, alpha, q, secret_distribution=secret_distribution, m=m, success_probability=success_probability, reduction_cost_model=reduction_cost_model) + return res_primal, res_dual + +# Testing SIS +# This analysis is given in Dilithium, C3 +# https://eprint.iacr.org/eprint-bin/getfile.pl?entry=2017/633&version=20180910:112250&file=633.pdf + + +# go from beta to delta for BKZ +def get_delta(beta): + return RR(beta/(2*pi*e) * (pi*beta)**(1/beta))**(1/(2*(beta-1))) + +def getGSA(d, q, beta, nrows): + delta = get_delta(beta) + log_delta =log(delta,2) + + log_q = log(q) + zone1 = nrows*[log_q] + slope = -(1/(beta-1))*log(beta/(2*pi*e)*(pi*beta)^(1/beta)) + zone2_length = int(floor(log(q)/-slope)) + zone2 = [log_q + i * slope for i in range(1, zone2_length+1)] + zone3 =(d-nrows)*[0] + GSA = zone1+zone2+zone3 + + lattice_vol = nrows*log_q + current_vol = sum(GSA[i] for i in range(d)) + + #correct the volume since now current_vol > lattice_vol + ind = 0 + while current_vol>lattice_vol: + current_vol -= GSA[ind] + current_vol += GSA[ind+d] + ind += 1 + GSA = GSA[ind:ind+d] + + i_index = max(0, nrows-ind) + j_index = min(i_index + zone2_length, d) + #error we make by overshooting the while loop + err = lattice_vol - current_vol + for i in range(i_index, j_index): + GSA[i] += err / (j_index-i_index+1) + + return GSA, i_index, j_index + + +def getGSA_noq(d, q, beta, nrows): + delta = get_delta(beta) + log_delta =log(delta,2) + + log_q = log(q) + slope = -(1/(beta-1))*log(beta/(2*pi*e)*(pi*beta)^(1/beta)) + + lattice_vol = nrows*log_q + current_vol = 0 + GSA_tmp = 0 + GSA = [] + for i in range(d): + GSA_tmp -= slope + current_vol += GSA_tmp + if lattice_vol=0, 'i_index>=0' + assert j_index<=len(GSA), 'j_index<=N' + assert i_index!=j_index, 'i_index!=j_index' + + Pr1 = (2.*B)/q + log_Pr1 = ((i_index)*(log(Pr1, 2))) + + norm_BKZ = exp(GSA[i_index]) + sigma = norm_BKZ / sqrt(j_index - i_index + 1) + Pr2 = erf(B / (sigma * sqrt(2.))) + log_Pr2 = (j_index-i_index+1)* log(Pr2, 2) + + logPr_total_ = (beta/2.0)*log(4./3., 2) + log_Pr1+log_Pr2 + logPr_total = min(0,logPr_total_) + log_runTimeSVP = log(model(beta),2).n() + log_runTime = log_runTimeSVP - logPr_total + + return [i_index, j_index, round(log_Pr1+log_Pr2), log_runTimeSVP, round(log_runTime)] + + +def SIS_esimates(n, l, k, q, B, model=SVP_Classical): + d = n*(k + l + 1) + m = n*k + best_rt = 10000 + beta_range = range(100, d, 10) + for beta in beta_range: + if (log(model(beta),2) > best_rt): + break + for w in [d]: + lat_dim = w + log_runtime = RunTime(beta, lat_dim, q, m, B, model=model) + if(log_runtime[4] +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum bb_status { + BB_OK = 0, + BB_INVALID_SIG = 1, + BB_BAD_ARG = 2, + BB_BUFFER_TOO_SMALL = 3, + BB_INTERNAL = 4, +} bb_status; + +typedef struct bb_algorithm { + const char *name; + size_t public_key_bytes; + size_t secret_key_bytes; + size_t signature_bytes; + + bb_status (*keygen)( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len); + + bb_status (*sign)( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len); + + bb_status (*verify)( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len); +} bb_algorithm; + +size_t bb_algorithm_count(void); +const bb_algorithm *bb_algorithm_at(size_t index); +const bb_algorithm *bb_find_algorithm(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/signature/adapters.h b/src/signature/adapters.h new file mode 100644 index 0000000..a119fb4 --- /dev/null +++ b/src/signature/adapters.h @@ -0,0 +1,87 @@ +#ifndef BATCH_BENCH_ADAPTERS_H +#define BATCH_BENCH_ADAPTERS_H + +#include "../batch_bench.h" + +bb_status bb_hypericum_keygen( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len); + +bb_status bb_hypericum_sign( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len); + +bb_status bb_hypericum_verify( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len); + +bb_status bb_shipovnik_keygen( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len); + +bb_status bb_shipovnik_sign( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len); + +bb_status bb_shipovnik_verify( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len); + +bb_status bb_kryzhovnik_keygen( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len); + +bb_status bb_kryzhovnik_sign( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len); + +bb_status bb_kryzhovnik_verify( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len); + +#endif diff --git a/src/signature/hypericum_adapter.c b/src/signature/hypericum_adapter.c new file mode 100644 index 0000000..ff114cf --- /dev/null +++ b/src/signature/hypericum_adapter.c @@ -0,0 +1,133 @@ +#include "adapters.h" + +#include "api.h" + +#include +#include + +bb_status bb_hypericum_keygen( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len) { + if (sk == NULL || pk == NULL || sk_len == NULL || pk_len == NULL) { + return BB_BAD_ARG; + } + if (sk_capacity < (size_t)CRYPTO_SECRETKEYBYTES || + pk_capacity < (size_t)CRYPTO_PUBLICKEYBYTES) { + return BB_BUFFER_TOO_SMALL; + } + + if (crypto_sign_keypair(pk, sk) != 0) { + return BB_INTERNAL; + } + + *sk_len = (size_t)CRYPTO_SECRETKEYBYTES; + *pk_len = (size_t)CRYPTO_PUBLICKEYBYTES; + return BB_OK; +} + +bb_status bb_hypericum_sign( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len) { + unsigned char *sm = NULL; + unsigned long long smlen = 0; + size_t required; + + (void)pk; + (void)pk_len; + + if (sk == NULL || msg == NULL || sig == NULL || sig_len == NULL) { + return BB_BAD_ARG; + } + if (sk_len != (size_t)CRYPTO_SECRETKEYBYTES) { + return BB_BAD_ARG; + } + + required = (size_t)CRYPTO_BYTES; + if (sig_capacity < required) { + return BB_BUFFER_TOO_SMALL; + } + + sm = (unsigned char *)malloc(required + msg_len); + if (sm == NULL) { + return BB_INTERNAL; + } + + if (crypto_sign(sm, &smlen, msg, (unsigned long long)msg_len, sk) != 0) { + free(sm); + return BB_INTERNAL; + } + + if (smlen < (unsigned long long)CRYPTO_BYTES) { + free(sm); + return BB_INTERNAL; + } + + memcpy(sig, sm, required); + *sig_len = required; + + free(sm); + return BB_OK; +} + +bb_status bb_hypericum_verify( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len) { + unsigned char *sm = NULL; + unsigned char *recovered = NULL; + unsigned long long recovered_len = 0; + bb_status status = BB_INVALID_SIG; + + if (pk == NULL || msg == NULL || sig == NULL) { + return BB_BAD_ARG; + } + if (pk_len != (size_t)CRYPTO_PUBLICKEYBYTES) { + return BB_BAD_ARG; + } + if (sig_len != (size_t)CRYPTO_BYTES) { + return BB_INVALID_SIG; + } + + sm = (unsigned char *)malloc(sig_len + msg_len); + recovered = (unsigned char *)malloc(msg_len); + if (sm == NULL || recovered == NULL) { + status = BB_INTERNAL; + goto cleanup; + } + + memcpy(sm, sig, sig_len); + memcpy(sm + sig_len, msg, msg_len); + + if (crypto_sign_open(recovered, &recovered_len, sm, + (unsigned long long)(sig_len + msg_len), pk) != 0) { + status = BB_INVALID_SIG; + goto cleanup; + } + + if (recovered_len != (unsigned long long)msg_len || + memcmp(recovered, msg, msg_len) != 0) { + status = BB_INVALID_SIG; + goto cleanup; + } + + status = BB_OK; + +cleanup: + free(sm); + free(recovered); + return status; +} diff --git a/src/signature/kryzhovnik_adapter.c b/src/signature/kryzhovnik_adapter.c new file mode 100644 index 0000000..8c9e7a4 --- /dev/null +++ b/src/signature/kryzhovnik_adapter.c @@ -0,0 +1,81 @@ +#include "adapters.h" + +#include "kryzhovnik_wrapper.h" + +bb_status bb_kryzhovnik_keygen( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len) { + if (sk == NULL || pk == NULL || sk_len == NULL || pk_len == NULL) { + return BB_BAD_ARG; + } + if (sk_capacity < (size_t)KRYZHOVNIK_SECRET_KEY_BYTES || + pk_capacity < (size_t)KRYZHOVNIK_PUBLIC_KEY_BYTES) { + return BB_BUFFER_TOO_SMALL; + } + + if (kryzhovnik_keygen(sk, sk_capacity, pk, pk_capacity) != KRYZHOVNIK_OK) { + return BB_INTERNAL; + } + *sk_len = (size_t)KRYZHOVNIK_SECRET_KEY_BYTES; + *pk_len = (size_t)KRYZHOVNIK_PUBLIC_KEY_BYTES; + return BB_OK; +} + +bb_status bb_kryzhovnik_sign( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len) { + if (sk == NULL || pk == NULL || msg == NULL || sig == NULL || sig_len == NULL) { + return BB_BAD_ARG; + } + if (sk_len != (size_t)KRYZHOVNIK_SECRET_KEY_BYTES || + pk_len != (size_t)KRYZHOVNIK_PUBLIC_KEY_BYTES) { + return BB_BAD_ARG; + } + if (sig_capacity < (size_t)KRYZHOVNIK_SIGNATURE_BYTES) { + return BB_BUFFER_TOO_SMALL; + } + + if (kryzhovnik_sign(sk, sk_len, pk, pk_len, msg, msg_len, + sig, sig_capacity, sig_len) != KRYZHOVNIK_OK) { + return BB_INTERNAL; + } + return BB_OK; +} + +bb_status bb_kryzhovnik_verify( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len) { + if (pk == NULL || msg == NULL || sig == NULL) { + return BB_BAD_ARG; + } + if (pk_len != (size_t)KRYZHOVNIK_PUBLIC_KEY_BYTES) { + return BB_BAD_ARG; + } + if (sig_len != (size_t)KRYZHOVNIK_SIGNATURE_BYTES) { + return BB_INVALID_SIG; + } + + switch (kryzhovnik_verify(pk, pk_len, sig, sig_len, msg, msg_len)) { + case KRYZHOVNIK_OK: + return BB_OK; + case KRYZHOVNIK_VERIFY_FAIL: + return BB_INVALID_SIG; + default: + return BB_BAD_ARG; + } +} diff --git a/src/signature/registry.c b/src/signature/registry.c new file mode 100644 index 0000000..89bdd7e --- /dev/null +++ b/src/signature/registry.c @@ -0,0 +1,65 @@ +#include "../batch_bench.h" +#include "adapters.h" + +#include "api.h" +#include "shipovnik.h" +#include "kryzhovnik_wrapper.h" + +#include + +static const bb_algorithm k_algorithms[] = { + { + .name = "hypericum", + .public_key_bytes = CRYPTO_PUBLICKEYBYTES, + .secret_key_bytes = CRYPTO_SECRETKEYBYTES, + .signature_bytes = CRYPTO_BYTES, + .keygen = bb_hypericum_keygen, + .sign = bb_hypericum_sign, + .verify = bb_hypericum_verify, + }, + { + .name = "shipovnik", + .public_key_bytes = SHIPOVNIK_PUBLICKEYBYTES, + .secret_key_bytes = SHIPOVNIK_SECRETKEYBYTES, + .signature_bytes = SHIPOVNIK_SIGBYTES, + .keygen = bb_shipovnik_keygen, + .sign = bb_shipovnik_sign, + .verify = bb_shipovnik_verify, + }, + { + .name = "kryzhovnik", + .public_key_bytes = KRYZHOVNIK_PUBLIC_KEY_BYTES, + .secret_key_bytes = KRYZHOVNIK_SECRET_KEY_BYTES, + .signature_bytes = KRYZHOVNIK_SIGNATURE_BYTES, + .keygen = bb_kryzhovnik_keygen, + .sign = bb_kryzhovnik_sign, + .verify = bb_kryzhovnik_verify, + }, +}; + +size_t bb_algorithm_count(void) { + return sizeof(k_algorithms) / sizeof(k_algorithms[0]); +} + +const bb_algorithm *bb_algorithm_at(size_t index) { + if (index >= bb_algorithm_count()) { + return NULL; + } + return &k_algorithms[index]; +} + +const bb_algorithm *bb_find_algorithm(const char *name) { + size_t i; + + if (name == NULL) { + return NULL; + } + + for (i = 0; i < bb_algorithm_count(); ++i) { + if (strcmp(k_algorithms[i].name, name) == 0) { + return &k_algorithms[i]; + } + } + + return NULL; +} diff --git a/src/signature/shipovnik_adapter.c b/src/signature/shipovnik_adapter.c new file mode 100644 index 0000000..2435984 --- /dev/null +++ b/src/signature/shipovnik_adapter.c @@ -0,0 +1,74 @@ +#include "adapters.h" + +#include "shipovnik.h" + +bb_status bb_shipovnik_keygen( + uint8_t *sk, + size_t sk_capacity, + size_t *sk_len, + uint8_t *pk, + size_t pk_capacity, + size_t *pk_len) { + if (sk == NULL || pk == NULL || sk_len == NULL || pk_len == NULL) { + return BB_BAD_ARG; + } + if (sk_capacity < (size_t)SHIPOVNIK_SECRETKEYBYTES || + pk_capacity < (size_t)SHIPOVNIK_PUBLICKEYBYTES) { + return BB_BUFFER_TOO_SMALL; + } + + shipovnik_generate_keys(sk, pk); + *sk_len = (size_t)SHIPOVNIK_SECRETKEYBYTES; + *pk_len = (size_t)SHIPOVNIK_PUBLICKEYBYTES; + return BB_OK; +} + +bb_status bb_shipovnik_sign( + const uint8_t *sk, + size_t sk_len, + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + uint8_t *sig, + size_t sig_capacity, + size_t *sig_len) { + size_t out_sig_len = 0; + + (void)pk; + (void)pk_len; + + if (sk == NULL || msg == NULL || sig == NULL || sig_len == NULL) { + return BB_BAD_ARG; + } + if (sk_len != (size_t)SHIPOVNIK_SECRETKEYBYTES) { + return BB_BAD_ARG; + } + if (sig_capacity < (size_t)SHIPOVNIK_SIGBYTES) { + return BB_BUFFER_TOO_SMALL; + } + + shipovnik_sign(sk, msg, msg_len, sig, &out_sig_len); + *sig_len = out_sig_len; + return BB_OK; +} + +bb_status bb_shipovnik_verify( + const uint8_t *pk, + size_t pk_len, + const uint8_t *msg, + size_t msg_len, + const uint8_t *sig, + size_t sig_len) { + if (pk == NULL || msg == NULL || sig == NULL) { + return BB_BAD_ARG; + } + if (pk_len != (size_t)SHIPOVNIK_PUBLICKEYBYTES) { + return BB_BAD_ARG; + } + if (sig_len > (size_t)SHIPOVNIK_SIGBYTES) { + return BB_INVALID_SIG; + } + + return shipovnik_verify(pk, sig, msg, msg_len) == 0 ? BB_OK : BB_INVALID_SIG; +} diff --git a/src/utils/message_gen.c b/src/utils/message_gen.c new file mode 100644 index 0000000..0079558 --- /dev/null +++ b/src/utils/message_gen.c @@ -0,0 +1,32 @@ +#include "message_gen.h" + +// Deterministic pseudo-random message generator for reproducible benchmarks. +// bb_mix64: SplitMix64 finalizer – mixes bits for good avalanche effect. +// bb_fill_message: fills 'out' with bytes derived from seed and message index. +// Same (seed, index, out_len) always yields identical output, no external storage. + +static uint64_t bb_mix64(uint64_t x) { + // SplitMix64 finalizer constants for deterministic diffusion. + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9ULL; + x ^= x >> 27; + x *= 0x94d049bb133111ebULL; + x ^= x >> 31; + return x; +} + +void bb_fill_message(uint8_t *out, size_t out_len, uint64_t seed, uint64_t index) { + uint64_t state; + size_t i; + + if (out == NULL) { + return; + } + + // 0x9e... is the golden-ratio increment used to decorrelate indices. + state = bb_mix64(seed ^ (index + 0x9e3779b97f4a7c15ULL)); + for (i = 0; i < out_len; ++i) { + state = bb_mix64(state + i + 1U); + out[i] = (uint8_t)(state & 0xFFU); + } +} diff --git a/src/utils/message_gen.h b/src/utils/message_gen.h new file mode 100644 index 0000000..1262885 --- /dev/null +++ b/src/utils/message_gen.h @@ -0,0 +1,11 @@ +#ifndef BATCH_BENCH_MESSAGE_GEN_H +#define BATCH_BENCH_MESSAGE_GEN_H + +#include +#include + +#define BB_DEFAULT_MESSAGE_SIZE 1024 + +void bb_fill_message(uint8_t *out, size_t out_len, uint64_t seed, uint64_t index); + +#endif diff --git a/src/utils/timer.c b/src/utils/timer.c new file mode 100644 index 0000000..d79aa95 --- /dev/null +++ b/src/utils/timer.c @@ -0,0 +1,35 @@ +#include "timer.h" + +#include + +uint64_t bb_now_monotonic_ns(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((uint64_t)ts.tv_sec * 1000000000ULL) + (uint64_t)ts.tv_nsec; +} + +void bb_timer_start(bb_timer *timer) { + if (timer == NULL) { + return; + } + timer->start_ns = bb_now_monotonic_ns(); + timer->end_ns = timer->start_ns; +} + +void bb_timer_stop(bb_timer *timer) { + if (timer == NULL) { + return; + } + timer->end_ns = bb_now_monotonic_ns(); +} + +uint64_t bb_timer_elapsed_ns(const bb_timer *timer) { + if (timer == NULL || timer->end_ns < timer->start_ns) { + return 0; + } + return timer->end_ns - timer->start_ns; +} + +double bb_timer_elapsed_ms(const bb_timer *timer) { + return (double)bb_timer_elapsed_ns(timer) / 1000000.0; +} diff --git a/src/utils/timer.h b/src/utils/timer.h new file mode 100644 index 0000000..37c8477 --- /dev/null +++ b/src/utils/timer.h @@ -0,0 +1,17 @@ +#ifndef BATCH_BENCH_TIMER_H +#define BATCH_BENCH_TIMER_H + +#include + +typedef struct bb_timer { + uint64_t start_ns; + uint64_t end_ns; +} bb_timer; + +uint64_t bb_now_monotonic_ns(void); +void bb_timer_start(bb_timer *timer); +void bb_timer_stop(bb_timer *timer); +uint64_t bb_timer_elapsed_ns(const bb_timer *timer); +double bb_timer_elapsed_ms(const bb_timer *timer); + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..7a4bde4 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(adapters_smoke adapters_smoke.c) + +target_link_libraries(adapters_smoke PRIVATE batch_bench_adapters) + +target_compile_features(adapters_smoke PRIVATE c_std_99) + +add_test(NAME adapters_smoke COMMAND adapters_smoke) diff --git a/tests/adapters_smoke.c b/tests/adapters_smoke.c new file mode 100644 index 0000000..f1e8a6c --- /dev/null +++ b/tests/adapters_smoke.c @@ -0,0 +1,69 @@ +#include "batch_bench.h" +#include "utils/message_gen.h" + +#include +#include +#include + +int main(void) { + size_t i; + uint8_t msg[BB_DEFAULT_MESSAGE_SIZE]; + + bb_fill_message(msg, sizeof(msg), 1, 0); + + for (i = 0; i < bb_algorithm_count(); ++i) { + const bb_algorithm *algo = bb_algorithm_at(i); + uint8_t *sk = (uint8_t *)malloc(algo->secret_key_bytes); + uint8_t *pk = (uint8_t *)malloc(algo->public_key_bytes); + uint8_t *sig = (uint8_t *)malloc(algo->signature_bytes); + size_t sk_len = 0; + size_t pk_len = 0; + size_t sig_len = 0; + + if (sk == NULL || pk == NULL || sig == NULL) { + free(sk); + free(pk); + free(sig); + return 1; + } + + if (algo->keygen(sk, algo->secret_key_bytes, &sk_len, + pk, algo->public_key_bytes, &pk_len) != BB_OK) { + free(sk); + free(pk); + free(sig); + return 1; + } + + if (algo->sign(sk, sk_len, pk, pk_len, msg, sizeof(msg), + sig, algo->signature_bytes, &sig_len) != BB_OK) { + free(sk); + free(pk); + free(sig); + return 1; + } + + if (algo->verify(pk, pk_len, msg, sizeof(msg), sig, sig_len) != BB_OK) { + free(sk); + free(pk); + free(sig); + return 1; + } + + msg[0] ^= 0x01U; + if (algo->verify(pk, pk_len, msg, sizeof(msg), sig, sig_len) == BB_OK) { + free(sk); + free(pk); + free(sig); + return 1; + } + msg[0] ^= 0x01U; + + free(sk); + free(pk); + free(sig); + } + + printf("adapters_smoke: ok\n"); + return 0; +} diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 730c40f..9a550ec 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -110,7 +110,11 @@ if(TARGET streebog AND EXISTS "${SHIPOVNIK_DIR}/src/shipovnik.c") ${SHIPOVNIK_DIR}/src ${STREEBOG_DIR} ) - target_compile_definitions(shipovnik PRIVATE ENTROPY_SOURCE="${ENTROPY_SOURCE}") + target_compile_definitions(shipovnik PRIVATE + ENTROPY_SOURCE="${ENTROPY_SOURCE}" + randombytes=shipovnik_randombytes + secure_erase=shipovnik_secure_erase + ) target_link_libraries(shipovnik PRIVATE streebog) add_executable(shipovnik_example ${SHIPOVNIK_DIR}/shipovnik_example.c) @@ -124,6 +128,24 @@ endif() # ------------------------------------------------------------------- set(KRYZHOVNIK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/kryzhovnik) if(EXISTS "${KRYZHOVNIK_DIR}/sign.c") + set(KRYZHOVNIK_PARAMSET "medium" CACHE STRING "Select a kryzhovnik parameter set") + set_property(CACHE KRYZHOVNIK_PARAMSET PROPERTY STRINGS "small" "medium" "large" "debug") + if(NOT KRYZHOVNIK_PARAMSET) + set(KRYZHOVNIK_PARAMSET "medium") + endif() + if(NOT KRYZHOVNIK_PARAMSET STREQUAL "small" AND + NOT KRYZHOVNIK_PARAMSET STREQUAL "medium" AND + NOT KRYZHOVNIK_PARAMSET STREQUAL "large" AND + NOT KRYZHOVNIK_PARAMSET STREQUAL "debug") + message(FATAL_ERROR "Unsupported KRYZHOVNIK_PARAMSET='${KRYZHOVNIK_PARAMSET}'. Use: small, medium, large, debug") + endif() + message(STATUS "Using Kryzhovnik parameter set ${KRYZHOVNIK_PARAMSET}") + + configure_file( + ${KRYZHOVNIK_DIR}/current-params.h.in + ${CMAKE_CURRENT_BINARY_DIR}/kryzhovnik/current-params.h + ) + find_package(PkgConfig QUIET) if(PkgConfig_FOUND) pkg_check_modules(OPENSSL QUIET IMPORTED_TARGET libcrypto) @@ -148,38 +170,32 @@ if(EXISTS "${KRYZHOVNIK_DIR}/sign.c") list(APPEND KRYZHOVNIK_SOURCES ${KRYZHOVNIK_DIR}/kryzhovnik_wrapper.c) endif() - set_source_files_properties(${KRYZHOVNIK_SOURCES} PROPERTIES LANGUAGE CXX) add_library(kryzhovnik STATIC ${KRYZHOVNIK_SOURCES}) - set_target_properties(kryzhovnik PROPERTIES LINKER_LANGUAGE CXX) target_include_directories(kryzhovnik PUBLIC $ + $ ) target_link_libraries(kryzhovnik PRIVATE ${KRYZHOVNIK_OPENSSL_TARGET}) target_compile_options(kryzhovnik PRIVATE - $<$,$>:-Wall -Wextra -Wshadow -Wconversion -O3 -march=native> - $<$:/W4 /O2> + $<$,$>:-Wall -Wextra -Wshadow -Wconversion -O3 -march=native> + $<$:/W4 /O2> ) + target_compile_features(kryzhovnik PRIVATE c_std_99) if(BUILD_TESTING AND EXISTS "${KRYZHOVNIK_DIR}/pqs_test.c") - set_source_files_properties(${KRYZHOVNIK_DIR}/pqs_test.c PROPERTIES LANGUAGE CXX) add_executable(kryzhovnik_test ${KRYZHOVNIK_DIR}/pqs_test.c) - set_target_properties(kryzhovnik_test PROPERTIES LINKER_LANGUAGE CXX) target_link_libraries(kryzhovnik_test PRIVATE kryzhovnik) add_test(NAME kryzhovnik_test COMMAND kryzhovnik_test) endif() if(BUILD_TESTING AND EXISTS "${KRYZHOVNIK_DIR}/test_wrapper.c") - set_source_files_properties(${KRYZHOVNIK_DIR}/test_wrapper.c PROPERTIES LANGUAGE CXX) add_executable(kryzhovnik_wrapper_test ${KRYZHOVNIK_DIR}/test_wrapper.c) - set_target_properties(kryzhovnik_wrapper_test PROPERTIES LINKER_LANGUAGE CXX) target_link_libraries(kryzhovnik_wrapper_test PRIVATE kryzhovnik) add_test(NAME kryzhovnik_wrapper_test COMMAND kryzhovnik_wrapper_test) endif() if(BUILD_TESTING AND EXISTS "${KRYZHOVNIK_DIR}/test_pqs.c") - set_source_files_properties(${KRYZHOVNIK_DIR}/test_pqs.c PROPERTIES LANGUAGE CXX) add_executable(kryzhovnik_api_test ${KRYZHOVNIK_DIR}/test_pqs.c) - set_target_properties(kryzhovnik_api_test PROPERTIES LINKER_LANGUAGE CXX) target_link_libraries(kryzhovnik_api_test PRIVATE kryzhovnik) add_test(NAME kryzhovnik_api_test COMMAND kryzhovnik_api_test) endif() diff --git a/third_party/kryzhovnik b/third_party/kryzhovnik index 710500a..9b900c0 160000 --- a/third_party/kryzhovnik +++ b/third_party/kryzhovnik @@ -1 +1 @@ -Subproject commit 710500a98a4cbd01c8572a0d8bc57498f390f776 +Subproject commit 9b900c073dbb0a1dbc1a6f2a563e0a943d205b2e