Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/ref",
"${workspaceFolder}/ref/params"

],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"PARAMS=sphincs-sha2-128f" // default value
],
"compilerPath": "C:\\msys64\\ucrt64\\bin\\gcc.exe",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"C_Cpp.dimInactiveRegions": false
}
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.html).

### Summary
This version introduces modifications to the `ref` implementation for performance analysis and benchmarking purposes. The core cryptographic logic of the original SPHINCS+ algorithm remains unchanged. All modifications are confined to the `ref` directory, supplementary testing scripts, and configuration files.

### Added
- **Performance Benchmarking Framework:**
- Introduced a `timing_info_t` struct in `ref/api.h` to capture execution time for key generation, signing, and verification steps.
- Added `print_timing_info()` function prototype in `ref/api.h` to display aggregated timing results.
- Added `run_test` function prototype in `ref/api.h` to facilitate running tests multiple times for stable performance metrics.
- **Automated Testing Support:**
- Added `ref/test/input.txt` to provide a consistent sample input for testing and debugging.
- **VS Code Configuration Support:**
- Added `.vscode/c_cpp_properties.json` to enhance development experience with debugging, code suggestions, and to fix all warnings.
- Configured include paths for all implementations (`ref`, `haraka-aesni`, `shake-avx2`, `sha2-avx2`) and parameter files.
- Defined default `PARAMS` macro for easier switching between parameter sets in the editor (note: this macro is only for code suggestions and does not affect the actual `make` process).

### Changed
- **Makefile Adjustments:**
- Updated `Makefile` in `ref` to support new benchmarking and testing options.

### Removed
- No changes in this version.

This project is a fork of the official [SPHINCS+](https://github.com/sphincs/sphincsplus) repository. The modifications, available at [quannguyen247/sphincsplus-dev](https://github.com/quannguyen247/sphincsplus-dev), are focused on performance analysis, benchmarking, and development tooling. The core cryptographic logic of the original public domain implementation of SPHINCS+ remains unchanged.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# Custom SPHINCS+ Implementation for PQC Research & Benchmarking

This repository is a fork of the official [SPHINCS+](https://github.com/sphincs/sphincsplus) implementation, customized by **quannguyen247** for the purpose of experimenting with, modifying, and benchmarking Post-Quantum Cryptography (PQC) algorithms.

## Purpose
The primary goal of this fork is to provide a flexible framework for research and detailed performance analysis. Key objectives include:
- **Algorithmic Experimentation:** Facilitating modifications to core components such as hash functions and tree structures to study their impact on security and efficiency.
- **Comparative Analysis:** Enabling side-by-side performance comparisons of different implementation strategies and optimizations.
- **Performance Metrics:** Precise execution time measurement for key generation, signing, and verification.

## Key Modifications
Significant changes have been made to the `ref` implementation to support these goals. For a detailed list of all modifications, please refer to the [CHANGELOG.md](CHANGELOG.md) file.

---

## SPHINCS+

This repository contains the software that accompanies the [SPHINCS+ submission](https://sphincs.org/) to [NIST's Post-Quantum Cryptography](https://csrc.nist.gov/Projects/Post-Quantum-Cryptography) project.
Expand Down
2 changes: 2 additions & 0 deletions ref/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ test/*
PQCsignKAT_*.rsp
PQCsignKAT_*.req
PQCgenKAT_sign
!test/input.txt
test/output.txt
47 changes: 32 additions & 15 deletions ref/Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
PARAMS = sphincs-haraka-128f
THASH = robust

CC=/usr/bin/gcc
CFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -Wconversion -Wmissing-prototypes -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS)
PARAMS = sphincs-sha2-128f
THASH = simple

CC = gcc
CFLAGS= -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \
-Wshadow -Wpointer-arith -Wconversion -O3 -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) -z noexecstack
ifeq ($(THASH),robust)
CFLAGS += -DSPX_ROBUST=1
endif
LDLIBS = -lcrypto

# OS-specific adjustments for randombytes
ifeq ($(OS),Windows_NT)
RANDOMBYTES_SRC = randombytes_win.c
LDLIBS += -lbcrypt
else
RANDOMBYTES_SRC = randombytes.c
endif

SOURCES = address.c randombytes.c merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c
SOURCES = address.c $(RANDOMBYTES_SRC) merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c
HEADERS = params.h address.h randombytes.h merkle.h wots.h wotsx1.h utils.h utilsx1.h fors.h api.h hash.h thash.h

ifneq (,$(findstring shake,$(PARAMS)))
Expand All @@ -20,7 +33,8 @@ ifneq (,$(findstring sha2,$(PARAMS)))
HEADERS += sha2.h
endif

DET_SOURCES = $(SOURCES:randombytes.%=rng.%)
# For deterministic KAT generation, replace randombytes with rng.c
DET_SOURCES = $(filter-out $(RANDOMBYTES_SRC),$(SOURCES)) rng.c
DET_HEADERS = $(HEADERS:randombytes.%=rng.%)

TESTS = test/fors \
Expand All @@ -30,6 +44,9 @@ BENCHMARK = test/benchmark

.PHONY: clean test benchmark

test_sphincsplus: test/test_sphincsplus.c $(SOURCES) $(HEADERS) Makefile
$(CC) $(CFLAGS) -o test/$@ $(SOURCES) $< $(LDLIBS)

default: PQCgenKAT_sign

all: PQCgenKAT_sign tests benchmarks
Expand All @@ -42,17 +59,17 @@ benchmarks: $(BENCHMARK)

benchmark: $(BENCHMARK:=.exec)

PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS)
PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) Makefile
$(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto

test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS)
test/benchmark: test/benchmark.c test/cycles.c $(DET_SOURCES) $(DET_HEADERS) Makefile
$(CC) $(CFLAGS) -o $@ test/cycles.c $(DET_SOURCES) $< $(LDLIBS)

test/%: test/%.c $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS)
test/%: test/%.c $(DET_SOURCES) $(DET_HEADERS) Makefile
$(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< $(LDLIBS)

test/haraka: test/haraka.c $(filter-out haraka.c,$(SOURCES)) $(HEADERS)
$(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(SOURCES)) $< $(LDLIBS)
test/haraka: test/haraka.c $(filter-out haraka.c,$(DET_SOURCES)) $(DET_HEADERS)
$(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(DET_SOURCES)) $< $(LDLIBS)

test/%.exec: test/%
@$<
Expand All @@ -62,4 +79,4 @@ clean:
-$(RM) $(BENCHMARK)
-$(RM) PQCgenKAT_sign
-$(RM) PQCsignKAT_*.rsp
-$(RM) PQCsignKAT_*.req
-$(RM) PQCsignKAT_*.req
Binary file added ref/PQCgenKAT_sign.exe
Binary file not shown.
22 changes: 22 additions & 0 deletions ref/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

#include "params.h"

// define macros
#define str(s) #s
#define xstr(s) str(s)

#define CRYPTO_ALGNAME "SPHINCS+"

#define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES
Expand Down Expand Up @@ -74,4 +78,22 @@ int crypto_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk);

// Timing struct for benchmarking
typedef struct {
double keygen;
double sign;
double verify;
double all;
double temp;
} timing_info_t;

// Expose global timing variable for test aggregation
extern timing_info_t g_time;

// Print and return timing info
timing_info_t print_timing_info(void);

// add prototypes
void run_test(const unsigned char *m, unsigned long long mlen, int test_idx);

#endif
23 changes: 23 additions & 0 deletions ref/cpu_used_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
#use chmod +x cpu_used_test.sh then ./cpu_used_test.sh

total_cpu=0
count=0

for i in {1..1000}
do
# Extract the numeric value (removes the % sign)
cpu=$( /usr/bin/time -v test_sphincsplus.exe 2>&1 | grep "Percent of CPU this job got" | grep -o ' [0-9]\+' )

if [[ -n "$cpu" ]]; then
total_cpu=$((total_cpu + cpu))
count=$((count + 1))
fi
done

if [ "$count" -gt 0 ]; then
average_cpu=$(echo "scale=2; $total_cpu / $count" | bc)
echo "Average CPU percent used: $average_cpu"
else
echo "Could not extract any CPU percent values!"
fi
20 changes: 20 additions & 0 deletions ref/randombytes_win.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* This is the Windows-specific implementation of randombytes, using BCryptGenRandom.
*/

#include <windows.h>
#include <bcrypt.h>
#include <stdio.h> /* For fprintf, stderr */
#include <stdlib.h> /* For exit */
#include "randombytes.h"

//#pragma comment(lib, "bcrypt.lib")

void randombytes(unsigned char *x, unsigned long long xlen)
{
NTSTATUS status = BCryptGenRandom(NULL, x, (ULONG)xlen, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (status != 0) { /* STATUS_SUCCESS is 0 */
fprintf(stderr, "Fatal error: BCryptGenRandom failed.\n");
exit(1);
}
}
11 changes: 6 additions & 5 deletions ref/sha2.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ static size_t crypto_hashblocks_sha256(uint8_t *statebytes,
return inlen;
}

static int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
// fix from int to unsigned long long
static unsigned long long crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
{
uint64_t state[8];
uint64_t a;
Expand Down Expand Up @@ -635,13 +636,13 @@ void mgf1_256(unsigned char *out, unsigned long outlen,

/* While we can fit in at least another full block of SHA256 output.. */
for (i = 0; (i+1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
u32_to_bytes(inbuf + inlen, i);
u32_to_bytes(inbuf + inlen, (uint32_t)i);
sha256(out, inbuf, inlen + 4);
out += SPX_SHA256_OUTPUT_BYTES;
}
/* Until we cannot anymore, and we fill the remainder. */
if (outlen > i*SPX_SHA256_OUTPUT_BYTES) {
u32_to_bytes(inbuf + inlen, i);
u32_to_bytes(inbuf + inlen, (uint32_t)i);
sha256(outbuf, inbuf, inlen + 4);
memcpy(out, outbuf, outlen - i*SPX_SHA256_OUTPUT_BYTES);
}
Expand All @@ -661,13 +662,13 @@ void mgf1_512(unsigned char *out, unsigned long outlen,

/* While we can fit in at least another full block of SHA512 output.. */
for (i = 0; (i+1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) {
u32_to_bytes(inbuf + inlen, i);
u32_to_bytes(inbuf + inlen, (uint32_t)i);
sha512(out, inbuf, inlen + 4);
out += SPX_SHA512_OUTPUT_BYTES;
}
/* Until we cannot anymore, and we fill the remainder. */
if (outlen > i*SPX_SHA512_OUTPUT_BYTES) {
u32_to_bytes(inbuf + inlen, i);
u32_to_bytes(inbuf + inlen, (uint32_t)i);
sha512(outbuf, inbuf, inlen + 4);
memcpy(out, outbuf, outlen - i*SPX_SHA512_OUTPUT_BYTES);
}
Expand Down
Loading