This starts a cleanup / refactor, but there is still some low-hanging fruit.master
@@ -5,5 +5,12 @@ test/test_xmss | |||||
test/test_xmss_fast | test/test_xmss_fast | ||||
test/test_xmssmt | test/test_xmssmt | ||||
test/test_xmssmt_fast | test/test_xmssmt_fast | ||||
test/test_xmss_XMSS* | |||||
test/test_xmss_fast_XMSS* | |||||
test/test_xmssmt_XMSSMT* | |||||
test/test_xmssmt_fast_XMSSMT* | |||||
test/speed | test/speed | ||||
test/gen_testvectors | |||||
test/gen_testvectors | |||||
params_XMSS_*.h | |||||
params_XMSSMT_*.h | |||||
params.h |
@@ -2,34 +2,45 @@ CC = /usr/bin/gcc | |||||
CFLAGS = -Wall -g -O3 -Wextra | CFLAGS = -Wall -g -O3 -Wextra | ||||
all: test/test_wots \ | all: test/test_wots \ | ||||
test/test_xmss \ | |||||
test/test_xmss_fast \ | |||||
test/test_xmssmt_fast \ | |||||
test/test_xmssmt | |||||
test/test_xmss_XMSS_SHA2-256_W16_H10 \ | |||||
test/test_xmss_fast_XMSS_SHA2-256_W16_H10 \ | |||||
test/test_xmssmt_fast_XMSSMT_SHA2-256_W16_H20_D4 \ | |||||
test/test_xmssmt_XMSSMT_SHA2-256_W16_H20_D4 | |||||
test/test_wots: hash.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c hash.h hash_address.h randombytes.h wots.h xmss_commons.h | |||||
.PHONY: clean | |||||
.PRECIOUS: params_%.h | |||||
params_%.h: params.h.py | |||||
python3 params.h.py $(patsubst params_%.h,%,$@) > $@ | |||||
test/test_wots: params_XMSS_SHA2-256_W16_H10.h hash.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c hash.h hash_address.h randombytes.h wots.h xmss_commons.h | |||||
ln -sf params_XMSS_SHA2-256_W16_H10.h params.h | |||||
$(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c -o $@ -lcrypto -lm | $(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c -o $@ -lcrypto -lm | ||||
test/test_xmss: hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c hash.h hash_address.h randombytes.h wots.h xmss.h xmss_commons.h | |||||
test/test_xmss_XMSS_%: params_XMSS_%.h hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c hash.h hash_address.h randombytes.h wots.h xmss.h xmss_commons.h | |||||
ln -sf params_XMSS_$(patsubst test/test_xmss_XMSS_%,%,$@).h params.h | |||||
$(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c -o $@ -lcrypto -lm | $(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmss.c -o $@ -lcrypto -lm | ||||
test/test_xmss_fast: hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c hash.h hash_address.h randombytes.h wots.h xmss_fast.h xmss_commons.h | |||||
test/test_xmss_fast_XMSS_%: params_XMSS_%.h hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c hash.h hash_address.h randombytes.h wots.h xmss_fast.h xmss_commons.h | |||||
ln -sf params_XMSS_$(patsubst test/test_xmss_fast_XMSS_%,%,$@).h params.h | |||||
$(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c -o $@ -lcrypto -lm | $(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmss_fast.c -o $@ -lcrypto -lm | ||||
test/test_xmssmt: hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c hash.h hash_address.h randombytes.h wots.h xmss.h xmss_commons.h | |||||
test/test_xmssmt_XMSSMT_%: params_XMSSMT_%.h hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c hash.h hash_address.h randombytes.h wots.h xmss.h xmss_commons.h | |||||
ln -sf params_XMSSMT_$(patsubst test/test_xmssmt_XMSSMT_%,%,$@).h params.h | |||||
$(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c -o $@ -lcrypto -lm | $(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss.c xmss_commons.c test/test_xmssmt.c -o $@ -lcrypto -lm | ||||
test/test_xmssmt_fast: hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c hash.h hash_address.h randombytes.h wots.h xmss_fast.h xmss_commons.h | |||||
$(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c -o $@ -lcrypto -lm | |||||
.PHONY: clean | |||||
test/test_xmssmt_fast_XMSSMT_%: params_XMSSMT_%.h hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c hash.h hash_address.h randombytes.h wots.h xmss_fast.h xmss_commons.h | |||||
ln -sf params_XMSSMT_$(patsubst test/test_xmssmt_fast_XMSSMT_%,%,$@).h params.h | |||||
$(CC) $(CFLAGS) hash.c hash_address.c randombytes.c wots.c xmss_fast.c xmss_commons.c test/test_xmssmt_fast.c -o $@ -lcrypto -lm | |||||
clean: | clean: | ||||
-rm *.o *.s | -rm *.o *.s | ||||
-rm test/test_wots | -rm test/test_wots | ||||
-rm test/test_xmss | |||||
-rm test/test_xmss_fast | |||||
-rm test/test_xmssmt | |||||
-rm test/test_xmssmt_fast | |||||
-rm test/test_xmss_XMSS* | |||||
-rm test/test_xmss_fast_XMSS* | |||||
-rm test/test_xmssmt_XMSS* | |||||
-rm test/test_xmssmt_fast_XMSS* | |||||
distclean: | |||||
-rm params.h | |||||
-rm params_XMSS*.h |
@@ -0,0 +1,172 @@ | |||||
#! /usr/bin/env python3 | |||||
# This script generates params.h files for the XMSS and XMSSMT parameter sets. | |||||
# It takes a single parameter, namely the name of the parameter set. | |||||
# Its output matches the following parameter tables. | |||||
# +-----------------------+-----------+----+----+-----+----+ | |||||
# | Name | Functions | n | w | len | h | | |||||
# +-----------------------+-----------+----+----+-----+----+ | |||||
# | REQUIRED: | | | | | | | |||||
# | | | | | | | | |||||
# | XMSS_SHA2-256_W16_H10 | SHA2-256 | 32 | 16 | 67 | 10 | | |||||
# | | | | | | | | |||||
# | XMSS_SHA2-256_W16_H16 | SHA2-256 | 32 | 16 | 67 | 16 | | |||||
# | | | | | | | | |||||
# | XMSS_SHA2-256_W16_H20 | SHA2-256 | 32 | 16 | 67 | 20 | | |||||
# | | | | | | | | |||||
# | OPTIONAL: | | | | | | | |||||
# | | | | | | | | |||||
# | XMSS_SHA2-512_W16_H10 | SHA2-512 | 64 | 16 | 131 | 10 | | |||||
# | | | | | | | | |||||
# | XMSS_SHA2-512_W16_H16 | SHA2-512 | 64 | 16 | 131 | 16 | | |||||
# | | | | | | | | |||||
# | XMSS_SHA2-512_W16_H20 | SHA2-512 | 64 | 16 | 131 | 20 | | |||||
# | | | | | | | | |||||
# | XMSS_SHAKE128_W16_H10 | SHAKE128 | 32 | 16 | 67 | 10 | | |||||
# | | | | | | | | |||||
# | XMSS_SHAKE128_W16_H16 | SHAKE128 | 32 | 16 | 67 | 16 | | |||||
# | | | | | | | | |||||
# | XMSS_SHAKE128_W16_H20 | SHAKE128 | 32 | 16 | 67 | 20 | | |||||
# | | | | | | | | |||||
# | XMSS_SHAKE256_W16_H10 | SHAKE256 | 64 | 16 | 131 | 10 | | |||||
# | | | | | | | | |||||
# | XMSS_SHAKE256_W16_H16 | SHAKE256 | 64 | 16 | 131 | 16 | | |||||
# | | | | | | | | |||||
# | XMSS_SHAKE256_W16_H20 | SHAKE256 | 64 | 16 | 131 | 20 | | |||||
# +-----------------------+-----------+----+----+-----+----+ | |||||
# +-----------------------------+-----------+----+----+-----+----+----+ | |||||
# | Name | Functions | n | w | len | h | d | | |||||
# +-----------------------------+-----------+----+----+-----+----+----+ | |||||
# | REQUIRED: | | | | | | | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H20_D2 | SHA2-256 | 32 | 16 | 67 | 20 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H20_D4 | SHA2-256 | 32 | 16 | 67 | 20 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H40_D2 | SHA2-256 | 32 | 16 | 67 | 40 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H40_D4 | SHA2-256 | 32 | 16 | 67 | 40 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H40_D8 | SHA2-256 | 32 | 16 | 67 | 40 | 8 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H60_D3 | SHA2-256 | 32 | 16 | 67 | 60 | 3 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H60_D6 | SHA2-256 | 32 | 16 | 67 | 60 | 6 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-256_W16_H60_D12 | SHA2-256 | 32 | 16 | 67 | 60 | 12 | | |||||
# | | | | | | | | | |||||
# | OPTIONAL: | | | | | | | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H20_D2 | SHA2-512 | 64 | 16 | 131 | 20 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H20_D4 | SHA2-512 | 64 | 16 | 131 | 20 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H40_D2 | SHA2-512 | 64 | 16 | 131 | 40 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H40_D4 | SHA2-512 | 64 | 16 | 131 | 40 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H40_D8 | SHA2-512 | 64 | 16 | 131 | 40 | 8 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H60_D3 | SHA2-512 | 64 | 16 | 131 | 60 | 3 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H60_D6 | SHA2-512 | 64 | 16 | 131 | 60 | 6 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHA2-512_W16_H60_D12 | SHA2-512 | 64 | 16 | 131 | 60 | 12 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H20_D2 | SHAKE128 | 32 | 16 | 67 | 20 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H20_D4 | SHAKE128 | 32 | 16 | 67 | 20 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H40_D2 | SHAKE128 | 32 | 16 | 67 | 40 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H40_D4 | SHAKE128 | 32 | 16 | 67 | 40 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H40_D8 | SHAKE128 | 32 | 16 | 67 | 40 | 8 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H60_D3 | SHAKE128 | 32 | 16 | 67 | 60 | 3 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H60_D6 | SHAKE128 | 32 | 16 | 67 | 60 | 6 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE128_W16_H60_D12 | SHAKE128 | 32 | 16 | 67 | 60 | 12 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H20_D2 | SHAKE256 | 64 | 16 | 131 | 20 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H20_D4 | SHAKE256 | 64 | 16 | 131 | 20 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H40_D2 | SHAKE256 | 64 | 16 | 131 | 40 | 2 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H40_D4 | SHAKE256 | 64 | 16 | 131 | 40 | 4 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H40_D8 | SHAKE256 | 64 | 16 | 131 | 40 | 8 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H60_D3 | SHAKE256 | 64 | 16 | 131 | 60 | 3 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H60_D6 | SHAKE256 | 64 | 16 | 131 | 60 | 6 | | |||||
# | | | | | | | | | |||||
# | XMSSMT_SHAKE256_W16_H60_D12 | SHAKE256 | 64 | 16 | 131 | 60 | 12 | | |||||
# +-----------------------------+-----------+----+----+-----+----+----+ | |||||
import sys | |||||
from math import log2, ceil, floor | |||||
if len(sys.argv) != 2: | |||||
print("Please supply a parameter identifier.", file=sys.stderr) | |||||
sys.exit(1) | |||||
param = sys.argv[1].split('_') | |||||
print("#ifndef PARAMS_H") | |||||
print("#define PARAMS_H") | |||||
print("") | |||||
print("// This file was automatically generated using params.h.py.") | |||||
print("// It matches the parameter set defined as", sys.argv[1], end=".\n") | |||||
functions = ["SHA2-256", "SHA2-512", "SHAKE128", "SHAKE256"] | |||||
nvalues = { | |||||
"SHA2-256": 32, | |||||
"SHA2-512": 64, | |||||
"SHAKE128": 32, | |||||
"SHAKE256": 64, | |||||
} | |||||
for i, func in enumerate(functions): | |||||
print("#define XMSS_{} {}".format(func.replace('-', '_'), i)) | |||||
print("#define XMSS_FUNC", functions.index(param[1])) | |||||
XMSS_N = int(nvalues[param[1]]) | |||||
print("#define XMSS_N", XMSS_N) | |||||
XMSS_WOTS_W = int(param[2][1:]) | |||||
print("#define XMSS_WOTS_W", XMSS_WOTS_W) | |||||
WOTS_LOG_W = int(log2(int(param[2][1:]))) | |||||
WOTS_LEN1 = ceil(((8*XMSS_N) / WOTS_LOG_W)) | |||||
WOTS_LEN2 = floor(log2(WOTS_LEN1*(XMSS_WOTS_W-1)) / WOTS_LOG_W) + 1 | |||||
print("#define XMSS_WOTS_LOG_W", WOTS_LOG_W) | |||||
print("#define XMSS_WOTS_LEN1", WOTS_LEN1) | |||||
print("#define XMSS_WOTS_LEN2", WOTS_LEN2) | |||||
print("#define XMSS_WOTS_LEN", WOTS_LEN1 + WOTS_LEN2) | |||||
WOTS_KEYSIZE = (WOTS_LEN1 + WOTS_LEN2) * XMSS_N | |||||
print("#define XMSS_WOTS_KEYSIZE", WOTS_KEYSIZE) | |||||
XMSS_H = int(param[3][1:]) | |||||
print("#define XMSS_FULLHEIGHT", XMSS_H) | |||||
if param[0] == 'XMSSMT': | |||||
XMSS_D = int(param[4][1:]) | |||||
XMSS_INDEX_LEN = floor((XMSS_H + 7) / 8) | |||||
else: | |||||
XMSS_INDEX_LEN = 4 # TODO fix this in the xmss code | |||||
XMSS_D = 1 | |||||
if int(param[3][1:]) % XMSS_D != 0: | |||||
print("Make sure that d divides h!", file=sys.stderr) | |||||
sys.exit(1) | |||||
print("#define XMSS_TREEHEIGHT", XMSS_H // XMSS_D) | |||||
print("#define XMSS_D", XMSS_D) | |||||
print("#define XMSS_INDEX_LEN", XMSS_INDEX_LEN) | |||||
XMSS_BYTES = XMSS_INDEX_LEN + XMSS_N + XMSS_D*WOTS_KEYSIZE + XMSS_H*XMSS_N; | |||||
print("#define XMSS_BYTES", XMSS_BYTES) | |||||
print("#define XMSS_PUBLICKEY_BYTES", 2*XMSS_N) | |||||
print("#define XMSS_PRIVATEKEY_BYTES", 4*XMSS_N + XMSS_INDEX_LEN) | |||||
print("#define XMSS_BDS_K", 2 + ((XMSS_H // XMSS_D) % 2)) # TODO figure out what we should do here | |||||
print("#endif") |
@@ -3,6 +3,7 @@ | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include "../wots.h" | #include "../wots.h" | ||||
#include "../randombytes.h" | #include "../randombytes.h" | ||||
#include "../params.h" | |||||
static void hexdump(unsigned char *a, size_t len) | static void hexdump(unsigned char *a, size_t len) | ||||
{ | { | ||||
@@ -13,30 +14,27 @@ static void hexdump(unsigned char *a, size_t len) | |||||
int main() | int main() | ||||
{ | { | ||||
int n = 32; | |||||
unsigned char seed[n]; | |||||
unsigned char pub_seed[n]; | |||||
wots_params params; | |||||
wots_set_params(¶ms, n, 16); | |||||
unsigned char seed[XMSS_N]; | |||||
unsigned char pub_seed[XMSS_N]; | |||||
int sig_len = params.len*params.n; | |||||
int sig_len = XMSS_WOTS_LEN*XMSS_N; | |||||
unsigned char pk1[sig_len]; | unsigned char pk1[sig_len]; | ||||
unsigned char pk2[sig_len]; | unsigned char pk2[sig_len]; | ||||
unsigned char sig[sig_len]; | unsigned char sig[sig_len]; | ||||
uint32_t addr[8] = {1,2,3,4}; | uint32_t addr[8] = {1,2,3,4}; | ||||
unsigned char msg[n]; | |||||
unsigned char msg[XMSS_N]; | |||||
int i; | int i; | ||||
randombytes(seed, n); | |||||
randombytes(pub_seed, n); | |||||
randombytes(msg, n); | |||||
randombytes(seed, XMSS_N); | |||||
randombytes(pub_seed, XMSS_N); | |||||
randombytes(msg, XMSS_N); | |||||
//randombytes(addr, 16); | //randombytes(addr, 16); | ||||
wots_pkgen(pk1, seed, ¶ms, pub_seed, addr); | |||||
wots_sign(sig, msg, seed, ¶ms, pub_seed, addr); | |||||
wots_pkFromSig(pk2, sig, msg, ¶ms, pub_seed, addr); | |||||
wots_pkgen(pk1, seed, pub_seed, addr); | |||||
wots_sign(sig, msg, seed, pub_seed, addr); | |||||
wots_pkFromSig(pk2, sig, msg, pub_seed, addr); | |||||
for (i = 0; i < sig_len; i++) | for (i = 0; i < sig_len; i++) | ||||
if (pk1[i] != pk2[i]) { | if (pk1[i] != pk2[i]) { | ||||
@@ -2,6 +2,8 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "../xmss.h" | #include "../xmss.h" | ||||
#include "../params.h" | |||||
#include "../randombytes.h" | |||||
#define MLEN 3491 | #define MLEN 3491 | ||||
#define SIGNATURES 50 | #define SIGNATURES 50 | ||||
@@ -13,32 +15,22 @@ unsigned long long mlen; | |||||
int main() | int main() | ||||
{ | { | ||||
int r; | int r; | ||||
unsigned long long i; | |||||
unsigned int n = 32; | |||||
unsigned int h = 8; | |||||
unsigned int w = 16; | |||||
unsigned long long i, j; | |||||
unsigned long errors = 0; | unsigned long errors = 0; | ||||
unsigned char sk[4*n+4]; | |||||
unsigned char pk[2*n]; | |||||
unsigned char sk[4*XMSS_N+4]; | |||||
unsigned char pk[2*XMSS_N]; | |||||
xmss_params p; | |||||
xmss_params *params = &p; | |||||
xmss_set_params(params, n, h, w); | |||||
unsigned long long signature_length = 4+n+params->wots_par.keysize+h*n; | |||||
unsigned long long signature_length = 4+XMSS_N+XMSS_WOTS_KEYSIZE+XMSS_TREEHEIGHT*XMSS_N; | |||||
unsigned char mo[MLEN+signature_length]; | unsigned char mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
FILE *urandom = fopen("/dev/urandom", "r"); | |||||
for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); | |||||
printf("keypair\n"); | printf("keypair\n"); | ||||
xmss_keypair(pk, sk, params); | |||||
xmss_keypair(pk, sk); | |||||
// check pub_seed in SK | // check pub_seed in SK | ||||
for (i = 0; i < n; i++) { | |||||
if (pk[n+i] != sk[4+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[4+3*n+i]) printf("pk.root != sk.root %llu",i); | |||||
for (i = 0; i < XMSS_N; i++) { | |||||
if (pk[XMSS_N+i] != sk[4+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[4+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i); | |||||
} | } | ||||
// check index | // check index | ||||
@@ -46,17 +38,24 @@ int main() | |||||
if (idx) printf("\nidx != 0 %lu\n",idx); | if (idx) printf("\nidx != 0 %lu\n",idx); | ||||
for (i = 0; i < SIGNATURES; i++) { | for (i = 0; i < SIGNATURES; i++) { | ||||
randombytes(mi, MLEN); | |||||
printf("sign\n"); | printf("sign\n"); | ||||
xmss_sign(sk, sm, &smlen, mi, MLEN, params); | |||||
xmss_sign(sk, sm, &smlen, mi, MLEN); | |||||
idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | ||||
printf("\nidx = %lu\n",idx); | printf("\nidx = %lu\n",idx); | ||||
for (j = 0; j < smlen; j++) { | |||||
printf("%02X", sm[j]); | |||||
} | |||||
printf("\n"); | |||||
r = memcmp(mi, sm+signature_length,MLEN); | r = memcmp(mi, sm+signature_length,MLEN); | ||||
printf("%d\n", r); | printf("%d\n", r); | ||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | printf("verify\n"); | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r); | printf("%d\n", r); | ||||
if (r != 0) errors++; | if (r != 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -65,7 +64,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[signature_length+10] ^= 1; | sm[signature_length+10] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -76,7 +75,7 @@ int main() | |||||
/* Modified index */ | /* Modified index */ | ||||
sm[signature_length+10] ^= 1; | sm[signature_length+10] ^= 1; | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -86,7 +85,7 @@ int main() | |||||
/* Modified R */ | /* Modified R */ | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
sm[5] ^= 1; | sm[5] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -96,7 +95,7 @@ int main() | |||||
/* Modified OTS sig */ | /* Modified OTS sig */ | ||||
sm[5] ^= 1; | sm[5] ^= 1; | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -106,7 +105,7 @@ int main() | |||||
/* Modified AUTH */ | /* Modified AUTH */ | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
sm[signature_length - 10] ^= 1; | sm[signature_length - 10] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -115,7 +114,6 @@ int main() | |||||
} | } | ||||
printf("#errors = %lu\n", errors); | printf("#errors = %lu\n", errors); | ||||
fclose(urandom); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -3,14 +3,12 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include "../xmss_fast.h" | #include "../xmss_fast.h" | ||||
#include "../params.h" | |||||
#include "../randombytes.h" | |||||
#define MLEN 3491 | #define MLEN 3491 | ||||
#define SIGNATURES 256 | #define SIGNATURES 256 | ||||
unsigned char mi[MLEN]; | |||||
unsigned long long smlen; | |||||
unsigned long long mlen; | |||||
unsigned long long t1, t2; | unsigned long long t1, t2; | ||||
unsigned long long cpucycles(void) | unsigned long long cpucycles(void) | ||||
@@ -24,55 +22,48 @@ int main() | |||||
{ | { | ||||
int r; | int r; | ||||
unsigned long long i; | unsigned long long i; | ||||
unsigned int n = 32; | |||||
unsigned int h = 8; | |||||
unsigned int w = 16; | |||||
unsigned int k = 2; | |||||
unsigned int k = XMSS_BDS_K; | |||||
unsigned long errors = 0; | unsigned long errors = 0; | ||||
unsigned char sk[4*n+4]; | |||||
unsigned char pk[2*n]; | |||||
xmss_params p; | |||||
xmss_params *params = &p; | |||||
xmss_set_params(params, n, h, w, k); | |||||
unsigned char sk[4*XMSS_N+4]; | |||||
unsigned char pk[2*XMSS_N]; | |||||
// TODO should we hide this into xmss_fast.c and just allocate a large enough chunk of memory here? | // TODO should we hide this into xmss_fast.c and just allocate a large enough chunk of memory here? | ||||
unsigned char stack[(h+1)*n]; | |||||
unsigned char stack[(XMSS_TREEHEIGHT+1)*XMSS_N]; | |||||
unsigned int stackoffset = 0; | unsigned int stackoffset = 0; | ||||
unsigned char stacklevels[h+1]; | |||||
unsigned char auth[(h)*n]; | |||||
unsigned char keep[(h >> 1)*n]; | |||||
treehash_inst treehash[h-k]; | |||||
unsigned char th_nodes[(h-k)*n]; | |||||
unsigned char retain[((1 << k) - k - 1)*n]; | |||||
unsigned char stacklevels[XMSS_TREEHEIGHT+1]; | |||||
unsigned char auth[(XMSS_TREEHEIGHT)*XMSS_N]; | |||||
unsigned char keep[(XMSS_TREEHEIGHT >> 1)*XMSS_N]; | |||||
treehash_inst treehash[XMSS_TREEHEIGHT-k]; | |||||
unsigned char th_nodes[(XMSS_TREEHEIGHT-k)*XMSS_N]; | |||||
unsigned char retain[((1 << k) - k - 1)*XMSS_N]; | |||||
bds_state s; | bds_state s; | ||||
bds_state *state = &s; | bds_state *state = &s; | ||||
for (i = 0; i < h-k; i++) | |||||
treehash[i].node = &th_nodes[n*i]; | |||||
for (i = 0; i < XMSS_TREEHEIGHT-k; i++) | |||||
treehash[i].node = &th_nodes[XMSS_N*i]; | |||||
xmss_set_bds_state(state, stack, stackoffset, stacklevels, auth, keep, treehash, retain, 0); | xmss_set_bds_state(state, stack, stackoffset, stacklevels, auth, keep, treehash, retain, 0); | ||||
unsigned long long signature_length = 4+n+params->wots_par.keysize+h*n; | |||||
unsigned long long signature_length = 4+XMSS_N+XMSS_WOTS_KEYSIZE+XMSS_TREEHEIGHT*XMSS_N; | |||||
unsigned char mi[MLEN]; | |||||
unsigned char mo[MLEN+signature_length]; | unsigned char mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
unsigned long long smlen; | |||||
unsigned long long mlen; | |||||
FILE *urandom = fopen("/dev/urandom", "r"); | |||||
for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); | |||||
randombytes(mi, MLEN); | |||||
printf("keypair\n"); | printf("keypair\n"); | ||||
t1 = cpucycles(); | t1 = cpucycles(); | ||||
xmss_keypair(pk, sk, state, params); | |||||
xmss_keypair(pk, sk, state); | |||||
t2 = cpucycles(); | t2 = cpucycles(); | ||||
printf("cycles = %llu\n", (t2-t1)); | printf("cycles = %llu\n", (t2-t1)); | ||||
double sec = (t2-t1)/3500000; | double sec = (t2-t1)/3500000; | ||||
printf("ms = %f\n", sec); | printf("ms = %f\n", sec); | ||||
int read; | |||||
read = fgetc(stdin); | |||||
// check pub_seed in SK | // check pub_seed in SK | ||||
for (i = 0; i < n; i++) { | |||||
if (pk[n+i] != sk[4+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[4+3*n+i]) printf("pk.root != sk.root %llu",i); | |||||
for (i = 0; i < XMSS_N; i++) { | |||||
if (pk[XMSS_N+i] != sk[4+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[4+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i); | |||||
} | } | ||||
// check index | // check index | ||||
@@ -81,7 +72,7 @@ int main() | |||||
for (i = 0; i < SIGNATURES; i++) { | for (i = 0; i < SIGNATURES; i++) { | ||||
printf("sign\n"); | printf("sign\n"); | ||||
xmss_sign(sk, state, sm, &smlen, mi, MLEN, params); | |||||
xmss_sign(sk, state, sm, &smlen, mi, MLEN); | |||||
idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | ||||
printf("\nidx = %lu\n",idx); | printf("\nidx = %lu\n",idx); | ||||
@@ -90,7 +81,7 @@ int main() | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | printf("verify\n"); | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r); | printf("%d\n", r); | ||||
if (r != 0) errors++; | if (r != 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -99,7 +90,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[signature_length+10] ^= 1; | sm[signature_length+10] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -110,7 +101,7 @@ int main() | |||||
/* Modified index */ | /* Modified index */ | ||||
sm[signature_length+10] ^= 1; | sm[signature_length+10] ^= 1; | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -120,7 +111,7 @@ int main() | |||||
/* Modified R */ | /* Modified R */ | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
sm[5] ^= 1; | sm[5] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -130,7 +121,7 @@ int main() | |||||
/* Modified OTS sig */ | /* Modified OTS sig */ | ||||
sm[5] ^= 1; | sm[5] ^= 1; | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -140,7 +131,7 @@ int main() | |||||
/* Modified AUTH */ | /* Modified AUTH */ | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
sm[signature_length - 10] ^= 1; | sm[signature_length - 10] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -150,7 +141,5 @@ int main() | |||||
printf("#errors = %lu\n", errors); | printf("#errors = %lu\n", errors); | ||||
printf("finished loop\n"); | printf("finished loop\n"); | ||||
fclose(urandom); | |||||
printf("closed urandom\n"); | |||||
return 0; | return 0; | ||||
} | } |
@@ -2,9 +2,11 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "../xmss.h" | #include "../xmss.h" | ||||
#include "../params.h" | |||||
#include "../randombytes.h" | |||||
#define MLEN 3491 | #define MLEN 3491 | ||||
#define SIGNATURES 1024 | |||||
#define SIGNATURES 5 | |||||
unsigned char mi[MLEN]; | unsigned char mi[MLEN]; | ||||
unsigned long long smlen; | unsigned long long smlen; | ||||
@@ -14,35 +16,24 @@ int main() | |||||
{ | { | ||||
int r; | int r; | ||||
unsigned long long i,j; | unsigned long long i,j; | ||||
unsigned int n = 32; | |||||
unsigned int h = 20; | |||||
unsigned int d = 5; | |||||
unsigned int w = 16; | |||||
xmssmt_params p; | |||||
xmssmt_params *params = &p; | |||||
xmssmt_set_params(params, n, h, d, w); | |||||
unsigned char sk[(XMSS_INDEX_LEN+4*XMSS_N)]; | |||||
unsigned char pk[2*XMSS_N]; | |||||
unsigned char sk[(params->index_len+4*n)]; | |||||
unsigned char pk[2*n]; | |||||
unsigned long long signature_length = params->index_len + n + (d*params->xmss_par.wots_par.keysize) + h*n; | |||||
unsigned long long signature_length = XMSS_INDEX_LEN + XMSS_N + (XMSS_D*XMSS_WOTS_KEYSIZE) + XMSS_FULLHEIGHT*XMSS_N; | |||||
unsigned char mo[MLEN+signature_length]; | unsigned char mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
FILE *urandom = fopen("/dev/urandom", "r"); | |||||
for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); | |||||
printf("keypair\n"); | printf("keypair\n"); | ||||
xmssmt_keypair(pk, sk, params); | |||||
xmssmt_keypair(pk, sk); | |||||
// check pub_seed in SK | // check pub_seed in SK | ||||
for (i = 0; i < n; i++) { | |||||
if (pk[n+i] != sk[params->index_len+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[params->index_len+3*n+i]) printf("pk.root != sk.root %llu",i); | |||||
for (i = 0; i < XMSS_N; i++) { | |||||
if (pk[XMSS_N+i] != sk[XMSS_INDEX_LEN+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[XMSS_INDEX_LEN+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i); | |||||
} | } | ||||
printf("pk checked\n"); | printf("pk checked\n"); | ||||
unsigned int idx_len = params->index_len; | |||||
unsigned int idx_len = XMSS_INDEX_LEN; | |||||
// check index | // check index | ||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
@@ -52,8 +43,10 @@ int main() | |||||
if (idx) printf("\nidx != 0: %llu\n",idx); | if (idx) printf("\nidx != 0: %llu\n",idx); | ||||
for (i = 0; i < SIGNATURES; i++) { | for (i = 0; i < SIGNATURES; i++) { | ||||
randombytes(mi, MLEN); | |||||
printf("sign\n"); | printf("sign\n"); | ||||
xmssmt_sign(sk, sm, &smlen, mi, MLEN, params); | |||||
xmssmt_sign(sk, sm, &smlen, mi, MLEN); | |||||
idx = 0; | idx = 0; | ||||
for (j = 0; j < idx_len; j++) { | for (j = 0; j < idx_len; j++) { | ||||
idx += ((unsigned long long)sm[j]) << 8*(idx_len - 1 - j); | idx += ((unsigned long long)sm[j]) << 8*(idx_len - 1 - j); | ||||
@@ -62,9 +55,14 @@ int main() | |||||
r = memcmp(mi, sm+signature_length,MLEN); | r = memcmp(mi, sm+signature_length,MLEN); | ||||
printf("%d\n", r); | printf("%d\n", r); | ||||
for (j = 0; j < smlen; j++) { | |||||
printf("%02X", sm[j]); | |||||
} | |||||
printf("\n"); | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | printf("verify\n"); | ||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r); | printf("%d\n", r); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", r); | printf("%d\n", r); | ||||
@@ -72,7 +70,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[52] ^= 1; | sm[52] ^= 1; | ||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
@@ -82,13 +80,12 @@ int main() | |||||
sm[260] ^= 1; | sm[260] ^= 1; | ||||
sm[52] ^= 1; | sm[52] ^= 1; | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
printf("%llu\n", mlen+1); | printf("%llu\n", mlen+1); | ||||
} | } | ||||
fclose(urandom); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -2,29 +2,33 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "../xmss_fast.h" | #include "../xmss_fast.h" | ||||
#include "../params.h" | |||||
#include "../randombytes.h" | |||||
#define MLEN 3491 | #define MLEN 3491 | ||||
#define SIGNATURES 4096 | |||||
#define SIGNATURES 128 | |||||
unsigned char mi[MLEN]; | unsigned char mi[MLEN]; | ||||
unsigned long long smlen; | unsigned long long smlen; | ||||
unsigned long long mlen; | unsigned long long mlen; | ||||
unsigned long long t1, t2; | |||||
unsigned long long cpucycles(void) | |||||
{ | |||||
unsigned long long result; | |||||
asm volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" : "=a" (result) :: "%rdx"); | |||||
return result; | |||||
} | |||||
int main() | int main() | ||||
{ | { | ||||
int r; | int r; | ||||
unsigned long long i,j; | unsigned long long i,j; | ||||
unsigned int n = 32; | |||||
unsigned int h = 12; | |||||
unsigned int d = 3; | |||||
unsigned int w = 16; | |||||
unsigned int k = 2; | |||||
xmssmt_params p; | |||||
xmssmt_params *params = &p; | |||||
if (xmssmt_set_params(params, n, h, d, w, k)) { | |||||
return 1; | |||||
} | |||||
unsigned int n = XMSS_N; | |||||
unsigned int h = XMSS_FULLHEIGHT; | |||||
unsigned int d = XMSS_D; | |||||
unsigned int k = XMSS_BDS_K; | |||||
unsigned int tree_h = h / d; | unsigned int tree_h = h / d; | ||||
@@ -36,7 +40,7 @@ int main() | |||||
treehash_inst treehash[(2*d-1) * (tree_h-k)]; | treehash_inst treehash[(2*d-1) * (tree_h-k)]; | ||||
unsigned char th_nodes[(2*d-1) * (tree_h-k)*n]; | unsigned char th_nodes[(2*d-1) * (tree_h-k)*n]; | ||||
unsigned char retain[(2*d-1) * ((1 << k) - k - 1)*n]; | unsigned char retain[(2*d-1) * ((1 << k) - k - 1)*n]; | ||||
unsigned char wots_sigs[d * params->xmss_par.wots_par.keysize]; | |||||
unsigned char wots_sigs[d * XMSS_WOTS_KEYSIZE]; | |||||
// first d are 'regular' states, second d are 'next'; top tree has no 'next' | // first d are 'regular' states, second d are 'next'; top tree has no 'next' | ||||
bds_state states[2*d-1]; | bds_state states[2*d-1]; | ||||
@@ -53,26 +57,25 @@ int main() | |||||
); | ); | ||||
} | } | ||||
unsigned char sk[(params->index_len+4*n)]; | |||||
unsigned char sk[(XMSS_INDEX_LEN+4*n)]; | |||||
unsigned char pk[2*n]; | unsigned char pk[2*n]; | ||||
unsigned long long signature_length = params->index_len + n + (d*params->xmss_par.wots_par.keysize) + h*n; | |||||
unsigned long long signature_length = XMSS_INDEX_LEN + n + (d*XMSS_WOTS_KEYSIZE) + h*n; | |||||
unsigned char mo[MLEN+signature_length]; | unsigned char mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
FILE *urandom = fopen("/dev/urandom", "r"); | |||||
for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); | |||||
randombytes(mi, MLEN); | |||||
printf("keypair\n"); | printf("keypair\n"); | ||||
xmssmt_keypair(pk, sk, states, wots_sigs, params); | |||||
xmssmt_keypair(pk, sk, states, wots_sigs); | |||||
// check pub_seed in SK | // check pub_seed in SK | ||||
for (i = 0; i < n; i++) { | for (i = 0; i < n; i++) { | ||||
if (pk[n+i] != sk[params->index_len+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[params->index_len+3*n+i]) printf("pk.root != sk.root %llu",i); | |||||
if (pk[n+i] != sk[XMSS_INDEX_LEN+2*n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); | |||||
if (pk[i] != sk[XMSS_INDEX_LEN+3*n+i]) printf("pk.root != sk.root %llu",i); | |||||
} | } | ||||
printf("pk checked\n"); | printf("pk checked\n"); | ||||
unsigned int idx_len = params->index_len; | |||||
unsigned int idx_len = XMSS_INDEX_LEN; | |||||
// check index | // check index | ||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
@@ -83,7 +86,10 @@ int main() | |||||
for (i = 0; i < SIGNATURES; i++) { | for (i = 0; i < SIGNATURES; i++) { | ||||
printf("sign\n"); | printf("sign\n"); | ||||
xmssmt_sign(sk, states, wots_sigs, sm, &smlen, mi, MLEN, params); | |||||
t1 = cpucycles(); | |||||
xmssmt_sign(sk, states, wots_sigs, sm, &smlen, mi, MLEN); | |||||
t2 = cpucycles(); | |||||
printf("signing cycles = %llu\n", (t2-t1)); | |||||
idx = 0; | idx = 0; | ||||
for (j = 0; j < idx_len; j++) { | for (j = 0; j < idx_len; j++) { | ||||
@@ -95,7 +101,10 @@ int main() | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | printf("verify\n"); | ||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
t1 = cpucycles(); | |||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk); | |||||
t2 = cpucycles(); | |||||
printf("verification cycles = %llu\n", (t2-t1)); | |||||
printf("%d\n", r); | printf("%d\n", r); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", r); | printf("%d\n", r); | ||||
@@ -103,7 +112,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[52] ^= 1; | sm[52] ^= 1; | ||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
@@ -113,13 +122,12 @@ int main() | |||||
sm[260] ^= 1; | sm[260] ^= 1; | ||||
sm[52] ^= 1; | sm[52] ^= 1; | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk, params); | |||||
r = xmssmt_sign_open(mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
printf("%llu\n", mlen+1); | printf("%llu\n", mlen+1); | ||||
} | } | ||||
fclose(urandom); | |||||
return 0; | return 0; | ||||
} | } |
@@ -14,31 +14,20 @@ Public domain. | |||||
#include "hash.h" | #include "hash.h" | ||||
#include "wots.h" | #include "wots.h" | ||||
#include "hash_address.h" | #include "hash_address.h" | ||||
void wots_set_params(wots_params *params, int n, int w) | |||||
{ | |||||
params->n = n; | |||||
params->w = w; | |||||
params->log_w = (int) log2(w); | |||||
params->len_1 = (int) ceil(((8*n) / params->log_w)); | |||||
params->len_2 = (int) floor(log2(params->len_1*(w-1)) / params->log_w) + 1; | |||||
params->len = params->len_1 + params->len_2; | |||||
params->keysize = params->len*params->n; | |||||
} | |||||
#include "params.h" | |||||
/** | /** | ||||
* Helper method for pseudorandom key generation | * Helper method for pseudorandom key generation | ||||
* Expands an n-byte array into a len*n byte array | * Expands an n-byte array into a len*n byte array | ||||
* this is done using PRF | * this is done using PRF | ||||
*/ | */ | ||||
static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params) | |||||
static void expand_seed(unsigned char *outseeds, const unsigned char *inseed) | |||||
{ | { | ||||
uint32_t i = 0; | uint32_t i = 0; | ||||
unsigned char ctr[32]; | unsigned char ctr[32]; | ||||
for(i = 0; i < params->len; i++){ | |||||
for(i = 0; i < XMSS_WOTS_LEN; i++){ | |||||
to_byte(ctr, i, 32); | to_byte(ctr, i, 32); | ||||
prf((outseeds + (i*params->n)), ctr, inseed, params->n); | |||||
prf(outseeds + i*XMSS_N, ctr, inseed, XMSS_N); | |||||
} | } | ||||
} | } | ||||
@@ -49,15 +38,15 @@ static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, co | |||||
* interpretes in as start-th value of the chain | * interpretes in as start-th value of the chain | ||||
* addr has to contain the address of the chain | * addr has to contain the address of the chain | ||||
*/ | */ | ||||
static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
uint32_t i, j; | uint32_t i, j; | ||||
for (j = 0; j < params->n; j++) | |||||
for (j = 0; j < XMSS_N; j++) | |||||
out[j] = in[j]; | out[j] = in[j]; | ||||
for (i = start; i < (start+steps) && i < params->w; i++) { | |||||
for (i = start; i < (start+steps) && i < XMSS_WOTS_W; i++) { | |||||
setHashADRS(addr, i); | setHashADRS(addr, i); | ||||
hash_f(out, out, pub_seed, addr, params->n); | |||||
hash_f(out, out, pub_seed, addr, XMSS_N); | |||||
} | } | ||||
} | } | ||||
@@ -66,7 +55,7 @@ static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int | |||||
* | * | ||||
* | * | ||||
*/ | */ | ||||
static void base_w(int *output, const int out_len, const unsigned char *input, const wots_params *params) | |||||
static void base_w(int *output, const int out_len, const unsigned char *input) | |||||
{ | { | ||||
int in = 0; | int in = 0; | ||||
int out = 0; | int out = 0; | ||||
@@ -80,84 +69,84 @@ static void base_w(int *output, const int out_len, const unsigned char *input, c | |||||
in++; | in++; | ||||
bits += 8; | bits += 8; | ||||
} | } | ||||
bits -= params->log_w; | |||||
output[out] = (total >> bits) & (params->w - 1); | |||||
bits -= XMSS_WOTS_LOG_W; | |||||
output[out] = (total >> bits) & (XMSS_WOTS_W - 1); | |||||
out++; | out++; | ||||
} | } | ||||
} | } | ||||
void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
void wots_pkgen(unsigned char *pk, const unsigned char *sk, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
uint32_t i; | uint32_t i; | ||||
expand_seed(pk, sk, params); | |||||
for (i=0; i < params->len; i++) { | |||||
expand_seed(pk, sk); | |||||
for (i=0; i < XMSS_WOTS_LEN; i++) { | |||||
setChainADRS(addr, i); | setChainADRS(addr, i); | ||||
gen_chain(pk+i*params->n, pk+i*params->n, 0, params->w-1, params, pub_seed, addr); | |||||
gen_chain(pk+i*XMSS_N, pk+i*XMSS_N, 0, XMSS_WOTS_W-1, pub_seed, addr); | |||||
} | } | ||||
} | } | ||||
void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
int basew[params->len]; | |||||
int basew[XMSS_WOTS_LEN]; | |||||
int csum = 0; | int csum = 0; | ||||
uint32_t i = 0; | uint32_t i = 0; | ||||
base_w(basew, params->len_1, msg, params); | |||||
base_w(basew, XMSS_WOTS_LEN1, msg); | |||||
for (i=0; i < params->len_1; i++) { | |||||
csum += params->w - 1 - basew[i]; | |||||
for (i=0; i < XMSS_WOTS_LEN1; i++) { | |||||
csum += XMSS_WOTS_W - 1 - basew[i]; | |||||
} | } | ||||
csum = csum << (8 - ((params->len_2 * params->log_w) % 8)); | |||||
csum = csum << (8 - ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) % 8)); | |||||
int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8; | |||||
int len_2_bytes = ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) + 7) / 8; | |||||
unsigned char csum_bytes[len_2_bytes]; | unsigned char csum_bytes[len_2_bytes]; | ||||
to_byte(csum_bytes, csum, len_2_bytes); | to_byte(csum_bytes, csum, len_2_bytes); | ||||
int csum_basew[len_2_bytes / params->log_w]; | |||||
base_w(csum_basew, params->len_2, csum_bytes, params); | |||||
int csum_basew[len_2_bytes / XMSS_WOTS_LOG_W]; | |||||
base_w(csum_basew, XMSS_WOTS_LEN2, csum_bytes); | |||||
for (i = 0; i < params->len_2; i++) { | |||||
basew[params->len_1 + i] = csum_basew[i]; | |||||
for (i = 0; i < XMSS_WOTS_LEN2; i++) { | |||||
basew[XMSS_WOTS_LEN1 + i] = csum_basew[i]; | |||||
} | } | ||||
expand_seed(sig, sk, params); | |||||
expand_seed(sig, sk); | |||||
for (i = 0; i < params->len; i++) { | |||||
for (i = 0; i < XMSS_WOTS_LEN; i++) { | |||||
setChainADRS(addr, i); | setChainADRS(addr, i); | ||||
gen_chain(sig+i*params->n, sig+i*params->n, 0, basew[i], params, pub_seed, addr); | |||||
gen_chain(sig+i*XMSS_N, sig+i*XMSS_N, 0, basew[i], pub_seed, addr); | |||||
} | } | ||||
} | } | ||||
void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
int basew[params->len]; | |||||
int basew[XMSS_WOTS_LEN]; | |||||
int csum = 0; | int csum = 0; | ||||
uint32_t i = 0; | uint32_t i = 0; | ||||
base_w(basew, params->len_1, msg, params); | |||||
base_w(basew, XMSS_WOTS_LEN1, msg); | |||||
for (i=0; i < params->len_1; i++) { | |||||
csum += params->w - 1 - basew[i]; | |||||
for (i=0; i < XMSS_WOTS_LEN1; i++) { | |||||
csum += XMSS_WOTS_W - 1 - basew[i]; | |||||
} | } | ||||
csum = csum << (8 - ((params->len_2 * params->log_w) % 8)); | |||||
csum = csum << (8 - ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) % 8)); | |||||
int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8; | |||||
int len_2_bytes = ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) + 7) / 8; | |||||
unsigned char csum_bytes[len_2_bytes]; | unsigned char csum_bytes[len_2_bytes]; | ||||
to_byte(csum_bytes, csum, len_2_bytes); | to_byte(csum_bytes, csum, len_2_bytes); | ||||
int csum_basew[len_2_bytes / params->log_w]; | |||||
base_w(csum_basew, params->len_2, csum_bytes, params); | |||||
int csum_basew[len_2_bytes / XMSS_WOTS_LOG_W]; | |||||
base_w(csum_basew, XMSS_WOTS_LEN2, csum_bytes); | |||||
for (i = 0; i < params->len_2; i++) { | |||||
basew[params->len_1 + i] = csum_basew[i]; | |||||
for (i = 0; i < XMSS_WOTS_LEN2; i++) { | |||||
basew[XMSS_WOTS_LEN1 + i] = csum_basew[i]; | |||||
} | } | ||||
for (i=0; i < params->len; i++) { | |||||
for (i=0; i < XMSS_WOTS_LEN; i++) { | |||||
setChainADRS(addr, i); | setChainADRS(addr, i); | ||||
gen_chain(pk+i*params->n, sig+i*params->n, basew[i], params->w-1-basew[i], params, pub_seed, addr); | |||||
gen_chain(pk+i*XMSS_N, sig+i*XMSS_N, basew[i], XMSS_WOTS_W-1-basew[i], pub_seed, addr); | |||||
} | } | ||||
} | } |
@@ -10,50 +10,24 @@ Public domain. | |||||
#include "stdint.h" | #include "stdint.h" | ||||
/** | |||||
* WOTS parameter set | |||||
* | |||||
* Meaning as defined in draft-irtf-cfrg-xmss-hash-based-signatures-02 | |||||
*/ | |||||
typedef struct { | |||||
uint32_t len_1; | |||||
uint32_t len_2; | |||||
uint32_t len; | |||||
uint32_t n; | |||||
uint32_t w; | |||||
uint32_t log_w; | |||||
uint32_t keysize; | |||||
} wots_params; | |||||
/** | |||||
* Set the WOTS parameters, | |||||
* only m, n, w are required as inputs, | |||||
* len, len_1, and len_2 are computed from those. | |||||
* | |||||
* Assumes w is a power of 2 | |||||
*/ | |||||
void wots_set_params(wots_params *params, int n, int w); | |||||
/** | /** | ||||
* WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key. | * WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key. | ||||
* For this it takes the seed pub_seed which is used to generate bitmasks and hash keys and the address of this WOTS key pair addr | * For this it takes the seed pub_seed which is used to generate bitmasks and hash keys and the address of this WOTS key pair addr | ||||
* | |||||
* params, must have been initialized before using wots_set params for params ! This is not done in this function | |||||
* | |||||
* | |||||
* Places the computed public key at address pk. | * Places the computed public key at address pk. | ||||
*/ | */ | ||||
void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); | |||||
void wots_pkgen(unsigned char *pk, const unsigned char *sk, const unsigned char *pub_seed, uint32_t addr[8]); | |||||
/** | /** | ||||
* Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig". | * Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig". | ||||
* | |||||
* | |||||
*/ | */ | ||||
void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); | |||||
void wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const unsigned char *pub_seed, uint32_t addr[8]); | |||||
/** | /** | ||||
* Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk. | * Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk. | ||||
* | |||||
* | |||||
*/ | */ | ||||
void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); | |||||
void wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const unsigned char *pub_seed, uint32_t addr[8]); | |||||
#endif | #endif |
@@ -17,89 +17,54 @@ Public domain. | |||||
//#include "prg.h" | //#include "prg.h" | ||||
#include "xmss_commons.h" | #include "xmss_commons.h" | ||||
#include "hash_address.h" | #include "hash_address.h" | ||||
#include "params.h" | |||||
// For testing | // For testing | ||||
#include "stdio.h" | #include "stdio.h" | ||||
/** | /** | ||||
* Used for pseudorandom keygeneration, | * Used for pseudorandom keygeneration, | ||||
* generates the seed for the WOTS keypair at address addr | * generates the seed for the WOTS keypair at address addr | ||||
* | * | ||||
* takes n byte sk_seed and returns n byte seed using 32 byte address addr. | |||||
* takes XMSS_N byte sk_seed and returns XMSS_N byte seed using 32 byte address addr. | |||||
*/ | */ | ||||
static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) | |||||
static void get_seed(unsigned char *seed, const unsigned char *sk_seed, uint32_t addr[8]) | |||||
{ | { | ||||
unsigned char bytes[32]; | unsigned char bytes[32]; | ||||
// Make sure that chain addr, hash addr, and key bit are 0! | // Make sure that chain addr, hash addr, and key bit are 0! | ||||
setChainADRS(addr,0); | |||||
setHashADRS(addr,0); | |||||
setKeyAndMask(addr,0); | |||||
setChainADRS(addr, 0); | |||||
setHashADRS(addr, 0); | |||||
setKeyAndMask(addr, 0); | |||||
// Generate pseudorandom value | // Generate pseudorandom value | ||||
addr_to_byte(bytes, addr); | addr_to_byte(bytes, addr); | ||||
prf(seed, bytes, sk_seed, n); | |||||
} | |||||
/** | |||||
* Initialize xmss params struct | |||||
* parameter names are the same as in the draft | |||||
*/ | |||||
void xmss_set_params(xmss_params *params, int n, int h, int w) | |||||
{ | |||||
params->h = h; | |||||
params->n = n; | |||||
wots_params wots_par; | |||||
wots_set_params(&wots_par, n, w); | |||||
params->wots_par = wots_par; | |||||
} | |||||
/** | |||||
* Initialize xmssmt_params struct | |||||
* parameter names are the same as in the draft | |||||
* | |||||
* Especially h is the total tree height, i.e. the XMSS trees have height h/d | |||||
*/ | |||||
void xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w) | |||||
{ | |||||
if (h % d) { | |||||
fprintf(stderr, "d must devide h without remainder!\n"); | |||||
return; | |||||
} | |||||
params->h = h; | |||||
params->d = d; | |||||
params->n = n; | |||||
params->index_len = (h + 7) / 8; | |||||
xmss_params xmss_par; | |||||
xmss_set_params(&xmss_par, n, (h/d), w); | |||||
params->xmss_par = xmss_par; | |||||
prf(seed, bytes, sk_seed, XMSS_N); | |||||
} | } | ||||
/** | /** | ||||
* Computes a leaf from a WOTS public key using an L-tree. | * Computes a leaf from a WOTS public key using an L-tree. | ||||
*/ | */ | ||||
static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
unsigned int l = params->wots_par.len; | |||||
unsigned int n = params->n; | |||||
unsigned int l = XMSS_WOTS_LEN; | |||||
uint32_t i = 0; | uint32_t i = 0; | ||||
uint32_t height = 0; | uint32_t height = 0; | ||||
uint32_t bound; | uint32_t bound; | ||||
//ADRS.setTreeHeight(0); | //ADRS.setTreeHeight(0); | ||||
setTreeHeight(addr, height); | setTreeHeight(addr, height); | ||||
while (l > 1) { | while (l > 1) { | ||||
bound = l >> 1; //floor(l / 2); | bound = l >> 1; //floor(l / 2); | ||||
for (i = 0; i < bound; i++) { | for (i = 0; i < bound; i++) { | ||||
//ADRS.setTreeIndex(i); | //ADRS.setTreeIndex(i); | ||||
setTreeIndex(addr, i); | setTreeIndex(addr, i); | ||||
//wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); | //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); | ||||
hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); | |||||
hash_h(wots_pk+i*XMSS_N, wots_pk+i*2*XMSS_N, pub_seed, addr, XMSS_N); | |||||
} | } | ||||
//if ( l % 2 == 1 ) { | //if ( l % 2 == 1 ) { | ||||
if (l & 1) { | if (l & 1) { | ||||
//pk[floor(l / 2) + 1] = pk[l]; | //pk[floor(l / 2) + 1] = pk[l]; | ||||
memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n); | |||||
memcpy(wots_pk+(l>>1)*XMSS_N, wots_pk+(l-1)*XMSS_N, XMSS_N); | |||||
//l = ceil(l / 2); | //l = ceil(l / 2); | ||||
l=(l>>1)+1; | l=(l>>1)+1; | ||||
} | } | ||||
@@ -112,21 +77,21 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param | |||||
setTreeHeight(addr, height); | setTreeHeight(addr, height); | ||||
} | } | ||||
//return pk[0]; | //return pk[0]; | ||||
memcpy(leaf, wots_pk, n); | |||||
memcpy(leaf, wots_pk, XMSS_N); | |||||
} | } | ||||
/** | /** | ||||
* Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address. | * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address. | ||||
*/ | */ | ||||
static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]) | |||||
static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]) | |||||
{ | { | ||||
unsigned char seed[params->n]; | |||||
unsigned char pk[params->wots_par.keysize]; | |||||
unsigned char seed[XMSS_N]; | |||||
unsigned char pk[XMSS_WOTS_KEYSIZE]; | |||||
get_seed(seed, sk_seed, params->n, ots_addr); | |||||
wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr); | |||||
get_seed(seed, sk_seed, ots_addr); | |||||
wots_pkgen(pk, seed, pub_seed, ots_addr); | |||||
l_tree(leaf, pk, params, pub_seed, ltree_addr); | |||||
l_tree(leaf, pk, pub_seed, ltree_addr); | |||||
} | } | ||||
/** | /** | ||||
@@ -134,15 +99,13 @@ static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, con | |||||
* Currently only used for key generation. | * Currently only used for key generation. | ||||
* | * | ||||
*/ | */ | ||||
static void treehash(unsigned char *node, uint16_t height, uint32_t index, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) | |||||
static void treehash(unsigned char *node, uint16_t height, uint32_t index, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) | |||||
{ | { | ||||
uint32_t idx = index; | uint32_t idx = index; | ||||
uint16_t n = params->n; | |||||
// use three different addresses because at this point we use all three formats in parallel | // use three different addresses because at this point we use all three formats in parallel | ||||
uint32_t ots_addr[8]; | uint32_t ots_addr[8]; | ||||
uint32_t ltree_addr[8]; | uint32_t ltree_addr[8]; | ||||
uint32_t node_addr[8]; | |||||
uint32_t node_addr[8]; | |||||
// only copy layer and tree address parts | // only copy layer and tree address parts | ||||
memcpy(ots_addr, addr, 12); | memcpy(ots_addr, addr, 12); | ||||
// type = ots | // type = ots | ||||
@@ -153,7 +116,7 @@ static void treehash(unsigned char *node, uint16_t height, uint32_t index, const | |||||
setType(node_addr, 2); | setType(node_addr, 2); | ||||
uint32_t lastnode, i; | uint32_t lastnode, i; | ||||
unsigned char stack[(height+1)*n]; | |||||
unsigned char stack[(height+1)*XMSS_N]; | |||||
uint16_t stacklevels[height+1]; | uint16_t stacklevels[height+1]; | ||||
unsigned int stackoffset=0; | unsigned int stackoffset=0; | ||||
@@ -162,68 +125,66 @@ static void treehash(unsigned char *node, uint16_t height, uint32_t index, const | |||||
for (; idx < lastnode; idx++) { | for (; idx < lastnode; idx++) { | ||||
setLtreeADRS(ltree_addr, idx); | setLtreeADRS(ltree_addr, idx); | ||||
setOTSADRS(ots_addr, idx); | setOTSADRS(ots_addr, idx); | ||||
gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); | |||||
gen_leaf_wots(stack+stackoffset*XMSS_N, sk_seed, pub_seed, ltree_addr, ots_addr); | |||||
stacklevels[stackoffset] = 0; | stacklevels[stackoffset] = 0; | ||||
stackoffset++; | stackoffset++; | ||||
while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { | while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { | ||||
setTreeHeight(node_addr, stacklevels[stackoffset-1]); | setTreeHeight(node_addr, stacklevels[stackoffset-1]); | ||||
setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); | setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); | ||||
hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, | |||||
node_addr, n); | |||||
hash_h(stack+(stackoffset-2)*XMSS_N, stack+(stackoffset-2)*XMSS_N, pub_seed, | |||||
node_addr, XMSS_N); | |||||
stacklevels[stackoffset-2]++; | stacklevels[stackoffset-2]++; | ||||
stackoffset--; | stackoffset--; | ||||
} | } | ||||
} | } | ||||
for (i=0; i < n; i++) | |||||
for (i=0; i < XMSS_N; i++) | |||||
node[i] = stack[i]; | node[i] = stack[i]; | ||||
} | } | ||||
/** | /** | ||||
* Computes a root node given a leaf and an authapth | * Computes a root node given a leaf and an authapth | ||||
*/ | */ | ||||
static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
unsigned int n = params->n; | |||||
uint32_t i, j; | uint32_t i, j; | ||||
unsigned char buffer[2*n]; | |||||
unsigned char buffer[2*XMSS_N]; | |||||
// If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. | // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. | ||||
// Otherwise, it is the other way around | // Otherwise, it is the other way around | ||||
if (leafidx & 1) { | if (leafidx & 1) { | ||||
for (j = 0; j < n; j++) | |||||
buffer[n+j] = leaf[j]; | |||||
for (j = 0; j < n; j++) | |||||
for (j = 0; j < XMSS_N; j++) | |||||
buffer[XMSS_N+j] = leaf[j]; | |||||
for (j = 0; j < XMSS_N; j++) | |||||
buffer[j] = authpath[j]; | buffer[j] = authpath[j]; | ||||
} | } | ||||
else { | else { | ||||
for (j = 0; j < n; j++) | |||||
for (j = 0; j < XMSS_N; j++) | |||||
buffer[j] = leaf[j]; | buffer[j] = leaf[j]; | ||||
for (j = 0; j < n; j++) | |||||
buffer[n+j] = authpath[j]; | |||||
for (j = 0; j < XMSS_N; j++) | |||||
buffer[XMSS_N+j] = authpath[j]; | |||||
} | } | ||||
authpath += n; | |||||
authpath += XMSS_N; | |||||
for (i=0; i < params->h-1; i++) { | |||||
for (i=0; i < XMSS_TREEHEIGHT-1; i++) { | |||||
setTreeHeight(addr, i); | setTreeHeight(addr, i); | ||||
leafidx >>= 1; | leafidx >>= 1; | ||||
setTreeIndex(addr, leafidx); | setTreeIndex(addr, leafidx); | ||||
if (leafidx&1) { | if (leafidx&1) { | ||||
hash_h(buffer+n, buffer, pub_seed, addr, n); | |||||
for (j = 0; j < n; j++) | |||||
hash_h(buffer+XMSS_N, buffer, pub_seed, addr, XMSS_N); | |||||
for (j = 0; j < XMSS_N; j++) | |||||
buffer[j] = authpath[j]; | buffer[j] = authpath[j]; | ||||
} | } | ||||
else { | else { | ||||
hash_h(buffer, buffer, pub_seed, addr, n); | |||||
for (j = 0; j < n; j++) | |||||
buffer[j+n] = authpath[j]; | |||||
hash_h(buffer, buffer, pub_seed, addr, XMSS_N); | |||||
for (j = 0; j < XMSS_N; j++) | |||||
buffer[j+XMSS_N] = authpath[j]; | |||||
} | } | ||||
authpath += n; | |||||
authpath += XMSS_N; | |||||
} | } | ||||
setTreeHeight(addr, (params->h-1)); | |||||
setTreeHeight(addr, (XMSS_TREEHEIGHT-1)); | |||||
leafidx >>= 1; | leafidx >>= 1; | ||||
setTreeIndex(addr, leafidx); | setTreeIndex(addr, leafidx); | ||||
hash_h(root, buffer, pub_seed, addr, n); | |||||
hash_h(root, buffer, pub_seed, addr, XMSS_N); | |||||
} | } | ||||
/** | /** | ||||
@@ -231,13 +192,11 @@ static void validate_authpath(unsigned char *root, const unsigned char *leaf, un | |||||
* For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009. | * For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009. | ||||
* It returns the authpath in "authpath" with the node on level 0 at index 0. | * It returns the authpath in "authpath" with the node on level 0 at index 0. | ||||
*/ | */ | ||||
static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8]) | |||||
static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, unsigned char *pub_seed, uint32_t addr[8]) | |||||
{ | { | ||||
uint32_t i, j, level; | uint32_t i, j, level; | ||||
uint32_t n = params->n; | |||||
uint32_t h = params->h; | |||||
unsigned char tree[2*(1<<h)*n]; | |||||
unsigned char tree[2*(1<<XMSS_TREEHEIGHT)*XMSS_N]; | |||||
uint32_t ots_addr[8]; | uint32_t ots_addr[8]; | ||||
uint32_t ltree_addr[8]; | uint32_t ltree_addr[8]; | ||||
@@ -251,32 +210,32 @@ static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, | |||||
setType(node_addr, 2); | setType(node_addr, 2); | ||||
// Compute all leaves | // Compute all leaves | ||||
for (i = 0; i < (1U << h); i++) { | |||||
for (i = 0; i < (1U << XMSS_TREEHEIGHT); i++) { | |||||
setLtreeADRS(ltree_addr, i); | setLtreeADRS(ltree_addr, i); | ||||
setOTSADRS(ots_addr, i); | setOTSADRS(ots_addr, i); | ||||
gen_leaf_wots(tree+((1<<h)*n + i*n), sk_seed, params, pub_seed, ltree_addr, ots_addr); | |||||
gen_leaf_wots(tree+((1<<XMSS_TREEHEIGHT)*XMSS_N + i*XMSS_N), sk_seed, pub_seed, ltree_addr, ots_addr); | |||||
} | } | ||||
level = 0; | level = 0; | ||||
// Compute tree: | // Compute tree: | ||||
// Outer loop: For each inner layer | // Outer loop: For each inner layer | ||||
for (i = (1<<h); i > 1; i>>=1) { | |||||
for (i = (1<<XMSS_TREEHEIGHT); i > 1; i>>=1) { | |||||
setTreeHeight(node_addr, level); | setTreeHeight(node_addr, level); | ||||
// Inner loop: for each pair of sibling nodes | // Inner loop: for each pair of sibling nodes | ||||
for (j = 0; j < i; j+=2) { | for (j = 0; j < i; j+=2) { | ||||
setTreeIndex(node_addr, j>>1); | setTreeIndex(node_addr, j>>1); | ||||
hash_h(tree + (i>>1)*n + (j>>1) * n, tree + i*n + j*n, pub_seed, node_addr, n); | |||||
hash_h(tree + (i>>1)*XMSS_N + (j>>1) * XMSS_N, tree + i*XMSS_N + j*XMSS_N, pub_seed, node_addr, XMSS_N); | |||||
} | } | ||||
level++; | level++; | ||||
} | } | ||||
// copy authpath | // copy authpath | ||||
for (i=0; i < h; i++) | |||||
memcpy(authpath + i*n, tree + ((1<<h)>>i)*n + ((leaf_idx >> i) ^ 1) * n, n); | |||||
for (i=0; i < XMSS_TREEHEIGHT; i++) | |||||
memcpy(authpath + i*XMSS_N, tree + ((1<<XMSS_TREEHEIGHT)>>i)*XMSS_N + ((leaf_idx >> i) ^ 1) * XMSS_N, XMSS_N); | |||||
// copy root | // copy root | ||||
memcpy(root, tree+n, n); | |||||
memcpy(root, tree+XMSS_N, XMSS_N); | |||||
} | } | ||||
@@ -285,24 +244,23 @@ static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, | |||||
* Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params) | |||||
int xmss_keypair(unsigned char *pk, unsigned char *sk) | |||||
{ | { | ||||
unsigned int n = params->n; | |||||
// Set idx = 0 | // Set idx = 0 | ||||
sk[0] = 0; | sk[0] = 0; | ||||
sk[1] = 0; | sk[1] = 0; | ||||
sk[2] = 0; | sk[2] = 0; | ||||
sk[3] = 0; | sk[3] = 0; | ||||
// Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) | |||||
randombytes(sk+4, 3*n); | |||||
// Init SK_SEED (XMSS_N byte), SK_PRF (XMSS_N byte), and PUB_SEED (XMSS_N byte) | |||||
randombytes(sk+4, 3*XMSS_N); | |||||
// Copy PUB_SEED to public key | // Copy PUB_SEED to public key | ||||
memcpy(pk+n, sk+4+2*n, n); | |||||
memcpy(pk+XMSS_N, sk+4+2*XMSS_N, XMSS_N); | |||||
uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
// Compute root | // Compute root | ||||
treehash(pk, params->h, 0, sk+4, params, sk+4+2*n, addr); | |||||
treehash(pk, XMSS_TREEHEIGHT, 0, sk+4, sk+4+2*XMSS_N, addr); | |||||
// copy root to sk | // copy root to sk | ||||
memcpy(sk+4+3*n, pk, n); | |||||
memcpy(sk+4+3*XMSS_N, pk, XMSS_N); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -313,26 +271,25 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params) | |||||
* 2. an updated secret key! | * 2. an updated secret key! | ||||
* | * | ||||
*/ | */ | ||||
int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params) | |||||
int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen) | |||||
{ | { | ||||
uint16_t n = params->n; | |||||
uint16_t i = 0; | uint16_t i = 0; | ||||
// Extract SK | // Extract SK | ||||
uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | ||||
unsigned char sk_seed[n]; | |||||
memcpy(sk_seed, sk+4, n); | |||||
unsigned char sk_prf[n]; | |||||
memcpy(sk_prf, sk+4+n, n); | |||||
unsigned char pub_seed[n]; | |||||
memcpy(pub_seed, sk+4+2*n, n); | |||||
unsigned char sk_seed[XMSS_N]; | |||||
memcpy(sk_seed, sk+4, XMSS_N); | |||||
unsigned char sk_prf[XMSS_N]; | |||||
memcpy(sk_prf, sk+4+XMSS_N, XMSS_N); | |||||
unsigned char pub_seed[XMSS_N]; | |||||
memcpy(pub_seed, sk+4+2*XMSS_N, XMSS_N); | |||||
// index as 32 bytes string | // index as 32 bytes string | ||||
unsigned char idx_bytes_32[32]; | unsigned char idx_bytes_32[32]; | ||||
to_byte(idx_bytes_32, idx, 32); | to_byte(idx_bytes_32, idx, 32); | ||||
unsigned char hash_key[3*n]; | |||||
unsigned char hash_key[3*XMSS_N]; | |||||
// Update SK | // Update SK | ||||
sk[0] = ((idx + 1) >> 24) & 255; | sk[0] = ((idx + 1) >> 24) & 255; | ||||
@@ -343,10 +300,10 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
// -- A productive implementation should use a file handle instead and write the updated secret key at this point! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
// Init working params | // Init working params | ||||
unsigned char R[n]; | |||||
unsigned char msg_h[n]; | |||||
unsigned char root[n]; | |||||
unsigned char ots_seed[n]; | |||||
unsigned char R[XMSS_N]; | |||||
unsigned char msg_h[XMSS_N]; | |||||
unsigned char root[XMSS_N]; | |||||
unsigned char ots_seed[XMSS_N]; | |||||
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
// --------------------------------- | // --------------------------------- | ||||
@@ -355,13 +312,13 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
// Message Hash: | // Message Hash: | ||||
// First compute pseudorandom value | // First compute pseudorandom value | ||||
prf(R, idx_bytes_32, sk_prf, n); | |||||
prf(R, idx_bytes_32, sk_prf, XMSS_N); | |||||
// Generate hash key (R || root || idx) | // Generate hash key (R || root || idx) | ||||
memcpy(hash_key, R, n); | |||||
memcpy(hash_key+n, sk+4+3*n, n); | |||||
to_byte(hash_key+2*n, idx, n); | |||||
memcpy(hash_key, R, XMSS_N); | |||||
memcpy(hash_key+XMSS_N, sk+4+3*XMSS_N, XMSS_N); | |||||
to_byte(hash_key+2*XMSS_N, idx, XMSS_N); | |||||
// Then use it for message digest | // Then use it for message digest | ||||
h_msg(msg_h, msg, msglen, hash_key, 3*n, n); | |||||
h_msg(msg_h, msg, msglen, hash_key, 3*XMSS_N, XMSS_N); | |||||
// Start collecting signature | // Start collecting signature | ||||
*sig_msg_len = 0; | *sig_msg_len = 0; | ||||
@@ -376,11 +333,11 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
*sig_msg_len += 4; | *sig_msg_len += 4; | ||||
// Copy R to signature | // Copy R to signature | ||||
for (i = 0; i < n; i++) | |||||
for (i = 0; i < XMSS_N; i++) | |||||
sig_msg[i] = R[i]; | sig_msg[i] = R[i]; | ||||
sig_msg += n; | |||||
*sig_msg_len += n; | |||||
sig_msg += XMSS_N; | |||||
*sig_msg_len += XMSS_N; | |||||
// ---------------------------------- | // ---------------------------------- | ||||
// Now we start to "really sign" | // Now we start to "really sign" | ||||
@@ -391,17 +348,17 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
setOTSADRS(ots_addr, idx); | setOTSADRS(ots_addr, idx); | ||||
// Compute seed for OTS key pair | // Compute seed for OTS key pair | ||||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||||
get_seed(ots_seed, sk_seed, ots_addr); | |||||
// Compute WOTS signature | // Compute WOTS signature | ||||
wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr); | |||||
wots_sign(sig_msg, msg_h, ots_seed, pub_seed, ots_addr); | |||||
sig_msg += params->wots_par.keysize; | |||||
*sig_msg_len += params->wots_par.keysize; | |||||
sig_msg += XMSS_WOTS_KEYSIZE; | |||||
*sig_msg_len += XMSS_WOTS_KEYSIZE; | |||||
compute_authpath_wots(root, sig_msg, idx, sk_seed, params, pub_seed, ots_addr); | |||||
sig_msg += params->h*n; | |||||
*sig_msg_len += params->h*n; | |||||
compute_authpath_wots(root, sig_msg, idx, sk_seed, pub_seed, ots_addr); | |||||
sig_msg += XMSS_TREEHEIGHT*XMSS_N; | |||||
*sig_msg_len += XMSS_TREEHEIGHT*XMSS_N; | |||||
//Whipe secret elements? | //Whipe secret elements? | ||||
//zerobytes(tsk, CRYPTO_SECRETKEYBYTES); | //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); | ||||
@@ -415,20 +372,19 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig | |||||
/** | /** | ||||
* Verifies a given message signature pair under a given public key. | * Verifies a given message signature pair under a given public key. | ||||
*/ | */ | ||||
int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params) | |||||
int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk) | |||||
{ | { | ||||
uint16_t n = params->n; | |||||
unsigned long long i, m_len; | unsigned long long i, m_len; | ||||
unsigned long idx=0; | unsigned long idx=0; | ||||
unsigned char wots_pk[params->wots_par.keysize]; | |||||
unsigned char pkhash[n]; | |||||
unsigned char root[n]; | |||||
unsigned char msg_h[n]; | |||||
unsigned char hash_key[3*n]; | |||||
unsigned char wots_pk[XMSS_WOTS_KEYSIZE]; | |||||
unsigned char pkhash[XMSS_N]; | |||||
unsigned char root[XMSS_N]; | |||||
unsigned char msg_h[XMSS_N]; | |||||
unsigned char hash_key[3*XMSS_N]; | |||||
unsigned char pub_seed[n]; | |||||
memcpy(pub_seed, pk+n, n); | |||||
unsigned char pub_seed[XMSS_N]; | |||||
memcpy(pub_seed, pk+XMSS_N, XMSS_N); | |||||
// Init addresses | // Init addresses | ||||
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
@@ -444,18 +400,18 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne | |||||
printf("verify:: idx = %lu\n", idx); | printf("verify:: idx = %lu\n", idx); | ||||
// Generate hash key (R || root || idx) | // Generate hash key (R || root || idx) | ||||
memcpy(hash_key, sig_msg+4,n); | |||||
memcpy(hash_key+n, pk, n); | |||||
to_byte(hash_key+2*n, idx, n); | |||||
memcpy(hash_key, sig_msg+4,XMSS_N); | |||||
memcpy(hash_key+XMSS_N, pk, XMSS_N); | |||||
to_byte(hash_key+2*XMSS_N, idx, XMSS_N); | |||||
sig_msg += (n+4); | |||||
sig_msg_len -= (n+4); | |||||
sig_msg += (XMSS_N+4); | |||||
sig_msg_len -= (XMSS_N+4); | |||||
// hash message | // hash message | ||||
unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; | |||||
unsigned long long tmp_sig_len = XMSS_WOTS_KEYSIZE+XMSS_TREEHEIGHT*XMSS_N; | |||||
m_len = sig_msg_len - tmp_sig_len; | m_len = sig_msg_len - tmp_sig_len; | ||||
h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); | |||||
h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*XMSS_N, XMSS_N); | |||||
//----------------------- | //----------------------- | ||||
// Verify signature | // Verify signature | ||||
@@ -464,22 +420,22 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne | |||||
// Prepare Address | // Prepare Address | ||||
setOTSADRS(ots_addr, idx); | setOTSADRS(ots_addr, idx); | ||||
// Check WOTS signature | // Check WOTS signature | ||||
wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr); | |||||
wots_pkFromSig(wots_pk, sig_msg, msg_h, pub_seed, ots_addr); | |||||
sig_msg += params->wots_par.keysize; | |||||
sig_msg_len -= params->wots_par.keysize; | |||||
sig_msg += XMSS_WOTS_KEYSIZE; | |||||
sig_msg_len -= XMSS_WOTS_KEYSIZE; | |||||
// Compute Ltree | // Compute Ltree | ||||
setLtreeADRS(ltree_addr, idx); | setLtreeADRS(ltree_addr, idx); | ||||
l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr); | |||||
l_tree(pkhash, wots_pk, pub_seed, ltree_addr); | |||||
// Compute root | // Compute root | ||||
validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr); | |||||
validate_authpath(root, pkhash, idx, sig_msg, pub_seed, node_addr); | |||||
sig_msg += params->h*n; | |||||
sig_msg_len -= params->h*n; | |||||
sig_msg += XMSS_TREEHEIGHT*XMSS_N; | |||||
sig_msg_len -= XMSS_TREEHEIGHT*XMSS_N; | |||||
for (i=0; i < n; i++) | |||||
for (i=0; i < XMSS_N; i++) | |||||
if (root[i] != pk[i]) | if (root[i] != pk[i]) | ||||
goto fail; | goto fail; | ||||
@@ -503,26 +459,25 @@ fail: | |||||
* Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] | * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params) | |||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk) | |||||
{ | { | ||||
unsigned int n = params->n; | |||||
uint16_t i; | uint16_t i; | ||||
// Set idx = 0 | // Set idx = 0 | ||||
for (i = 0; i < params->index_len; i++) { | |||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
sk[i] = 0; | sk[i] = 0; | ||||
} | } | ||||
// Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) | |||||
randombytes(sk+params->index_len, 3*n); | |||||
// Init SK_SEED (XMSS_N byte), SK_PRF (XMSS_N byte), and PUB_SEED (XMSS_N byte) | |||||
randombytes(sk+XMSS_INDEX_LEN, 3*XMSS_N); | |||||
// Copy PUB_SEED to public key | // Copy PUB_SEED to public key | ||||
memcpy(pk+n, sk+params->index_len+2*n, n); | |||||
memcpy(pk+XMSS_N, sk+XMSS_INDEX_LEN+2*XMSS_N, XMSS_N); | |||||
// Set address to point on the single tree on layer d-1 | // Set address to point on the single tree on layer d-1 | ||||
uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
setLayerADRS(addr, (params->d-1)); | |||||
setLayerADRS(addr, (XMSS_D-1)); | |||||
// Compute root | // Compute root | ||||
treehash(pk, params->xmss_par.h, 0, sk+params->index_len, &(params->xmss_par), pk+n, addr); | |||||
memcpy(sk+params->index_len+3*n, pk, n); | |||||
treehash(pk, XMSS_TREEHEIGHT, 0, sk+XMSS_INDEX_LEN, pk+XMSS_N, addr); | |||||
memcpy(sk+XMSS_INDEX_LEN+3*XMSS_N, pk, XMSS_N); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -533,40 +488,37 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params) | |||||
* 2. an updated secret key! | * 2. an updated secret key! | ||||
* | * | ||||
*/ | */ | ||||
int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params) | |||||
int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen) | |||||
{ | { | ||||
unsigned int n = params->n; | |||||
unsigned int tree_h = params->xmss_par.h; | |||||
unsigned int idx_len = params->index_len; | |||||
uint64_t idx_tree; | uint64_t idx_tree; | ||||
uint32_t idx_leaf; | uint32_t idx_leaf; | ||||
uint64_t i; | uint64_t i; | ||||
unsigned char sk_seed[n]; | |||||
unsigned char sk_prf[n]; | |||||
unsigned char pub_seed[n]; | |||||
unsigned char sk_seed[XMSS_N]; | |||||
unsigned char sk_prf[XMSS_N]; | |||||
unsigned char pub_seed[XMSS_N]; | |||||
// Init working params | // Init working params | ||||
unsigned char R[n]; | |||||
unsigned char hash_key[3*n]; | |||||
unsigned char msg_h[n]; | |||||
unsigned char root[n]; | |||||
unsigned char ots_seed[n]; | |||||
unsigned char R[XMSS_N]; | |||||
unsigned char hash_key[3*XMSS_N]; | |||||
unsigned char msg_h[XMSS_N]; | |||||
unsigned char root[XMSS_N]; | |||||
unsigned char ots_seed[XMSS_N]; | |||||
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
unsigned char idx_bytes_32[32]; | unsigned char idx_bytes_32[32]; | ||||
// Extract SK | // Extract SK | ||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | |||||
idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i); | |||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
idx |= ((unsigned long long)sk[i]) << 8*(XMSS_INDEX_LEN - 1 - i); | |||||
} | } | ||||
memcpy(sk_seed, sk+idx_len, n); | |||||
memcpy(sk_prf, sk+idx_len+n, n); | |||||
memcpy(pub_seed, sk+idx_len+2*n, n); | |||||
memcpy(sk_seed, sk+XMSS_INDEX_LEN, XMSS_N); | |||||
memcpy(sk_prf, sk+XMSS_INDEX_LEN+XMSS_N, XMSS_N); | |||||
memcpy(pub_seed, sk+XMSS_INDEX_LEN+2*XMSS_N, XMSS_N); | |||||
// Update SK | // Update SK | ||||
for (i = 0; i < idx_len; i++) { | |||||
sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255; | |||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
sk[i] = ((idx + 1) >> 8*(XMSS_INDEX_LEN - 1 - i)) & 255; | |||||
} | } | ||||
// -- Secret key for this non-forward-secure version is now updated. | // -- Secret key for this non-forward-secure version is now updated. | ||||
// -- A productive implementation should use a file handle instead and write the updated secret key at this point! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
@@ -579,32 +531,32 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s | |||||
// Message Hash: | // Message Hash: | ||||
// First compute pseudorandom value | // First compute pseudorandom value | ||||
to_byte(idx_bytes_32, idx, 32); | to_byte(idx_bytes_32, idx, 32); | ||||
prf(R, idx_bytes_32, sk_prf, n); | |||||
prf(R, idx_bytes_32, sk_prf, XMSS_N); | |||||
// Generate hash key (R || root || idx) | // Generate hash key (R || root || idx) | ||||
memcpy(hash_key, R, n); | |||||
memcpy(hash_key+n, sk+idx_len+3*n, n); | |||||
to_byte(hash_key+2*n, idx, n); | |||||
memcpy(hash_key, R, XMSS_N); | |||||
memcpy(hash_key+XMSS_N, sk+XMSS_INDEX_LEN+3*XMSS_N, XMSS_N); | |||||
to_byte(hash_key+2*XMSS_N, idx, XMSS_N); | |||||
// Then use it for message digest | // Then use it for message digest | ||||
h_msg(msg_h, msg, msglen, hash_key, 3*n, n); | |||||
h_msg(msg_h, msg, msglen, hash_key, 3*XMSS_N, XMSS_N); | |||||
// Start collecting signature | // Start collecting signature | ||||
*sig_msg_len = 0; | *sig_msg_len = 0; | ||||
// Copy index to signature | // Copy index to signature | ||||
for (i = 0; i < idx_len; i++) { | |||||
sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255; | |||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
sig_msg[i] = (idx >> 8*(XMSS_INDEX_LEN - 1 - i)) & 255; | |||||
} | } | ||||
sig_msg += idx_len; | |||||
*sig_msg_len += idx_len; | |||||
sig_msg += XMSS_INDEX_LEN; | |||||
*sig_msg_len += XMSS_INDEX_LEN; | |||||
// Copy R to signature | // Copy R to signature | ||||
for (i=0; i < n; i++) | |||||
for (i=0; i < XMSS_N; i++) | |||||
sig_msg[i] = R[i]; | sig_msg[i] = R[i]; | ||||
sig_msg += n; | |||||
*sig_msg_len += n; | |||||
sig_msg += XMSS_N; | |||||
*sig_msg_len += XMSS_N; | |||||
// ---------------------------------- | // ---------------------------------- | ||||
// Now we start to "really sign" | // Now we start to "really sign" | ||||
@@ -614,47 +566,47 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s | |||||
// Prepare Address | // Prepare Address | ||||
setType(ots_addr, 0); | setType(ots_addr, 0); | ||||
idx_tree = idx >> tree_h; | |||||
idx_leaf = (idx & ((1 << tree_h)-1)); | |||||
idx_tree = idx >> XMSS_TREEHEIGHT; | |||||
idx_leaf = (idx & ((1 << XMSS_TREEHEIGHT)-1)); | |||||
setLayerADRS(ots_addr, 0); | setLayerADRS(ots_addr, 0); | ||||
setTreeADRS(ots_addr, idx_tree); | setTreeADRS(ots_addr, idx_tree); | ||||
setOTSADRS(ots_addr, idx_leaf); | setOTSADRS(ots_addr, idx_leaf); | ||||
// Compute seed for OTS key pair | // Compute seed for OTS key pair | ||||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||||
get_seed(ots_seed, sk_seed, ots_addr); | |||||
// Compute WOTS signature | // Compute WOTS signature | ||||
wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||||
wots_sign(sig_msg, msg_h, ots_seed, pub_seed, ots_addr); | |||||
sig_msg += params->xmss_par.wots_par.keysize; | |||||
*sig_msg_len += params->xmss_par.wots_par.keysize; | |||||
sig_msg += XMSS_WOTS_KEYSIZE; | |||||
*sig_msg_len += XMSS_WOTS_KEYSIZE; | |||||
compute_authpath_wots(root, sig_msg, idx_leaf, sk_seed, &(params->xmss_par), pub_seed, ots_addr); | |||||
sig_msg += tree_h*n; | |||||
*sig_msg_len += tree_h*n; | |||||
compute_authpath_wots(root, sig_msg, idx_leaf, sk_seed, pub_seed, ots_addr); | |||||
sig_msg += XMSS_TREEHEIGHT*XMSS_N; | |||||
*sig_msg_len += XMSS_TREEHEIGHT*XMSS_N; | |||||
// Now loop over remaining layers... | // Now loop over remaining layers... | ||||
unsigned int j; | unsigned int j; | ||||
for (j = 1; j < params->d; j++) { | |||||
for (j = 1; j < XMSS_D; j++) { | |||||
// Prepare Address | // Prepare Address | ||||
idx_leaf = (idx_tree & ((1 << tree_h)-1)); | |||||
idx_tree = idx_tree >> tree_h; | |||||
idx_leaf = (idx_tree & ((1 << XMSS_TREEHEIGHT)-1)); | |||||
idx_tree = idx_tree >> XMSS_TREEHEIGHT; | |||||
setLayerADRS(ots_addr, j); | setLayerADRS(ots_addr, j); | ||||
setTreeADRS(ots_addr, idx_tree); | setTreeADRS(ots_addr, idx_tree); | ||||
setOTSADRS(ots_addr, idx_leaf); | setOTSADRS(ots_addr, idx_leaf); | ||||
// Compute seed for OTS key pair | // Compute seed for OTS key pair | ||||
get_seed(ots_seed, sk_seed, n, ots_addr); | |||||
get_seed(ots_seed, sk_seed, ots_addr); | |||||
// Compute WOTS signature | // Compute WOTS signature | ||||
wots_sign(sig_msg, root, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||||
wots_sign(sig_msg, root, ots_seed, pub_seed, ots_addr); | |||||
sig_msg += params->xmss_par.wots_par.keysize; | |||||
*sig_msg_len += params->xmss_par.wots_par.keysize; | |||||
sig_msg += XMSS_WOTS_KEYSIZE; | |||||
*sig_msg_len += XMSS_WOTS_KEYSIZE; | |||||
compute_authpath_wots(root, sig_msg, idx_leaf, sk_seed, &(params->xmss_par), pub_seed, ots_addr); | |||||
sig_msg += tree_h*n; | |||||
*sig_msg_len += tree_h*n; | |||||
compute_authpath_wots(root, sig_msg, idx_leaf, sk_seed, pub_seed, ots_addr); | |||||
sig_msg += XMSS_TREEHEIGHT*XMSS_N; | |||||
*sig_msg_len += XMSS_TREEHEIGHT*XMSS_N; | |||||
} | } | ||||
//Whipe secret elements? | //Whipe secret elements? | ||||
@@ -669,25 +621,21 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s | |||||
/** | /** | ||||
* Verifies a given message signature pair under a given public key. | * Verifies a given message signature pair under a given public key. | ||||
*/ | */ | ||||
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params) | |||||
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk) | |||||
{ | { | ||||
unsigned int n = params->n; | |||||
unsigned int tree_h = params->xmss_par.h; | |||||
unsigned int idx_len = params->index_len; | |||||
uint64_t idx_tree; | uint64_t idx_tree; | ||||
uint32_t idx_leaf; | uint32_t idx_leaf; | ||||
unsigned long long i, m_len; | unsigned long long i, m_len; | ||||
unsigned long long idx=0; | unsigned long long idx=0; | ||||
unsigned char wots_pk[params->xmss_par.wots_par.keysize]; | |||||
unsigned char pkhash[n]; | |||||
unsigned char root[n]; | |||||
unsigned char msg_h[n]; | |||||
unsigned char hash_key[3*n]; | |||||
unsigned char wots_pk[XMSS_WOTS_KEYSIZE]; | |||||
unsigned char pkhash[XMSS_N]; | |||||
unsigned char root[XMSS_N]; | |||||
unsigned char msg_h[XMSS_N]; | |||||
unsigned char hash_key[3*XMSS_N]; | |||||
unsigned char pub_seed[n]; | |||||
memcpy(pub_seed, pk+n, n); | |||||
unsigned char pub_seed[XMSS_N]; | |||||
memcpy(pub_seed, pk+XMSS_N, XMSS_N); | |||||
// Init addresses | // Init addresses | ||||
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
@@ -695,25 +643,25 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig | |||||
uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
// Extract index | // Extract index | ||||
for (i = 0; i < idx_len; i++) { | |||||
idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i)); | |||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
idx |= ((unsigned long long)sig_msg[i]) << (8*(XMSS_INDEX_LEN - 1 - i)); | |||||
} | } | ||||
printf("verify:: idx = %llu\n", idx); | printf("verify:: idx = %llu\n", idx); | ||||
sig_msg += idx_len; | |||||
sig_msg_len -= idx_len; | |||||
sig_msg += XMSS_INDEX_LEN; | |||||
sig_msg_len -= XMSS_INDEX_LEN; | |||||
// Generate hash key (R || root || idx) | // Generate hash key (R || root || idx) | ||||
memcpy(hash_key, sig_msg,n); | |||||
memcpy(hash_key+n, pk, n); | |||||
to_byte(hash_key+2*n, idx, n); | |||||
memcpy(hash_key, sig_msg,XMSS_N); | |||||
memcpy(hash_key+XMSS_N, pk, XMSS_N); | |||||
to_byte(hash_key+2*XMSS_N, idx, XMSS_N); | |||||
sig_msg += n; | |||||
sig_msg_len -= n; | |||||
sig_msg += XMSS_N; | |||||
sig_msg_len -= XMSS_N; | |||||
// hash message | // hash message | ||||
unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); | |||||
unsigned long long tmp_sig_len = (XMSS_D * XMSS_WOTS_KEYSIZE) + (XMSS_FULLHEIGHT * XMSS_N); | |||||
m_len = sig_msg_len - tmp_sig_len; | m_len = sig_msg_len - tmp_sig_len; | ||||
h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); | |||||
h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*XMSS_N, XMSS_N); | |||||
//----------------------- | //----------------------- | ||||
@@ -721,8 +669,8 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig | |||||
//----------------------- | //----------------------- | ||||
// Prepare Address | // Prepare Address | ||||
idx_tree = idx >> tree_h; | |||||
idx_leaf = (idx & ((1 << tree_h)-1)); | |||||
idx_tree = idx >> XMSS_TREEHEIGHT; | |||||
idx_leaf = (idx & ((1 << XMSS_TREEHEIGHT)-1)); | |||||
setLayerADRS(ots_addr, 0); | setLayerADRS(ots_addr, 0); | ||||
setTreeADRS(ots_addr, idx_tree); | setTreeADRS(ots_addr, idx_tree); | ||||
setType(ots_addr, 0); | setType(ots_addr, 0); | ||||
@@ -736,25 +684,25 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig | |||||
setOTSADRS(ots_addr, idx_leaf); | setOTSADRS(ots_addr, idx_leaf); | ||||
// Check WOTS signature | // Check WOTS signature | ||||
wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||||
wots_pkFromSig(wots_pk, sig_msg, msg_h, pub_seed, ots_addr); | |||||
sig_msg += params->xmss_par.wots_par.keysize; | |||||
sig_msg_len -= params->xmss_par.wots_par.keysize; | |||||
sig_msg += XMSS_WOTS_KEYSIZE; | |||||
sig_msg_len -= XMSS_WOTS_KEYSIZE; | |||||
// Compute Ltree | // Compute Ltree | ||||
setLtreeADRS(ltree_addr, idx_leaf); | setLtreeADRS(ltree_addr, idx_leaf); | ||||
l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); | |||||
l_tree(pkhash, wots_pk, pub_seed, ltree_addr); | |||||
// Compute root | // Compute root | ||||
validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr); | |||||
validate_authpath(root, pkhash, idx_leaf, sig_msg, pub_seed, node_addr); | |||||
sig_msg += tree_h*n; | |||||
sig_msg_len -= tree_h*n; | |||||
sig_msg += XMSS_TREEHEIGHT*XMSS_N; | |||||
sig_msg_len -= XMSS_TREEHEIGHT*XMSS_N; | |||||
for (i = 1; i < params->d; i++) { | |||||
for (i = 1; i < XMSS_D; i++) { | |||||
// Prepare Address | // Prepare Address | ||||
idx_leaf = (idx_tree & ((1 << tree_h)-1)); | |||||
idx_tree = idx_tree >> tree_h; | |||||
idx_leaf = (idx_tree & ((1 << XMSS_TREEHEIGHT)-1)); | |||||
idx_tree = idx_tree >> XMSS_TREEHEIGHT; | |||||
setLayerADRS(ots_addr, i); | setLayerADRS(ots_addr, i); | ||||
setTreeADRS(ots_addr, idx_tree); | setTreeADRS(ots_addr, idx_tree); | ||||
@@ -769,24 +717,24 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig | |||||
setOTSADRS(ots_addr, idx_leaf); | setOTSADRS(ots_addr, idx_leaf); | ||||
// Check WOTS signature | // Check WOTS signature | ||||
wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr); | |||||
wots_pkFromSig(wots_pk, sig_msg, root, pub_seed, ots_addr); | |||||
sig_msg += params->xmss_par.wots_par.keysize; | |||||
sig_msg_len -= params->xmss_par.wots_par.keysize; | |||||
sig_msg += XMSS_WOTS_KEYSIZE; | |||||
sig_msg_len -= XMSS_WOTS_KEYSIZE; | |||||
// Compute Ltree | // Compute Ltree | ||||
setLtreeADRS(ltree_addr, idx_leaf); | setLtreeADRS(ltree_addr, idx_leaf); | ||||
l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); | |||||
l_tree(pkhash, wots_pk, pub_seed, ltree_addr); | |||||
// Compute root | // Compute root | ||||
validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr); | |||||
validate_authpath(root, pkhash, idx_leaf, sig_msg, pub_seed, node_addr); | |||||
sig_msg += tree_h*n; | |||||
sig_msg_len -= tree_h*n; | |||||
sig_msg += XMSS_TREEHEIGHT*XMSS_N; | |||||
sig_msg_len -= XMSS_TREEHEIGHT*XMSS_N; | |||||
} | } | ||||
for (i=0; i < n; i++) | |||||
for (i=0; i < XMSS_N; i++) | |||||
if (root[i] != pk[i]) | if (root[i] != pk[i]) | ||||
goto fail; | goto fail; | ||||
@@ -15,37 +15,12 @@ typedef struct{ | |||||
unsigned int subleaf; | unsigned int subleaf; | ||||
} leafaddr; | } leafaddr; | ||||
typedef struct{ | |||||
wots_params wots_par; | |||||
unsigned int n; | |||||
unsigned int h; | |||||
} xmss_params; | |||||
typedef struct{ | |||||
xmss_params xmss_par; | |||||
unsigned int n; | |||||
unsigned int h; | |||||
unsigned int d; | |||||
unsigned int index_len; | |||||
} xmssmt_params; | |||||
/** | |||||
* Initializes parameter set. | |||||
* Needed, for any of the other methods. | |||||
*/ | |||||
void xmss_set_params(xmss_params *params, int n, int h, int w); | |||||
/** | |||||
* Initialize xmssmt_params struct | |||||
* parameter names are the same as in the draft | |||||
* | |||||
* Especially h is the total tree height, i.e. the XMSS trees have height h/d | |||||
*/ | |||||
void xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w); | |||||
/** | /** | ||||
* Generates a XMSS key pair for a given parameter set. | * Generates a XMSS key pair for a given parameter set. | ||||
* Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params); | |||||
int xmss_keypair(unsigned char *pk, unsigned char *sk); | |||||
/** | /** | ||||
* Signs a message. | * Signs a message. | ||||
* Returns | * Returns | ||||
@@ -53,20 +28,20 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params); | |||||
* 2. an updated secret key! | * 2. an updated secret key! | ||||
* | * | ||||
*/ | */ | ||||
int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg,unsigned long long msglen, const xmss_params *params); | |||||
int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen); | |||||
/** | /** | ||||
* Verifies a given message signature pair under a given public key. | * Verifies a given message signature pair under a given public key. | ||||
* | * | ||||
* Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). | * Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). | ||||
*/ | */ | ||||
int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned char *sig_msg,unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params); | |||||
int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk); | |||||
/* | /* | ||||
* Generates a XMSSMT key pair for a given parameter set. | * Generates a XMSSMT key pair for a given parameter set. | ||||
* Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params); | |||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk); | |||||
/** | /** | ||||
* Signs a message. | * Signs a message. | ||||
* Returns | * Returns | ||||
@@ -74,10 +49,10 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params); | |||||
* 2. an updated secret key! | * 2. an updated secret key! | ||||
* | * | ||||
*/ | */ | ||||
int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params); | |||||
int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen); | |||||
/** | /** | ||||
* Verifies a given message signature pair under a given public key. | * Verifies a given message signature pair under a given public key. | ||||
*/ | */ | ||||
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params); | |||||
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk); | |||||
#endif | #endif | ||||
@@ -15,21 +15,6 @@ typedef struct{ | |||||
unsigned int subleaf; | unsigned int subleaf; | ||||
} leafaddr; | } leafaddr; | ||||
typedef struct{ | |||||
wots_params wots_par; | |||||
unsigned int n; | |||||
unsigned int h; | |||||
unsigned int k; | |||||
} xmss_params; | |||||
typedef struct{ | |||||
xmss_params xmss_par; | |||||
unsigned int n; | |||||
unsigned int h; | |||||
unsigned int d; | |||||
unsigned int index_len; | |||||
} xmssmt_params; | |||||
typedef struct{ | typedef struct{ | ||||
unsigned int h; | unsigned int h; | ||||
unsigned int next_idx; | unsigned int next_idx; | ||||
@@ -54,24 +39,12 @@ typedef struct { | |||||
* parameter names are the same as used in the description of the BDS traversal | * parameter names are the same as used in the description of the BDS traversal | ||||
*/ | */ | ||||
void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf); | void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf); | ||||
/** | |||||
* Initializes parameter set. | |||||
* Needed, for any of the other methods. | |||||
*/ | |||||
int xmss_set_params(xmss_params *params, int n, int h, int w, int k); | |||||
/** | |||||
* Initialize xmssmt_params struct | |||||
* parameter names are the same as in the draft | |||||
* | |||||
* Especially h is the total tree height, i.e. the XMSS trees have height h/d | |||||
*/ | |||||
int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k); | |||||
/** | /** | ||||
* Generates a XMSS key pair for a given parameter set. | * Generates a XMSS key pair for a given parameter set. | ||||
* Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params); | |||||
int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state); | |||||
/** | /** | ||||
* Signs a message. | * Signs a message. | ||||
* Returns | * Returns | ||||
@@ -79,20 +52,20 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_pa | |||||
* 2. an updated secret key! | * 2. an updated secret key! | ||||
* | * | ||||
*/ | */ | ||||
int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg,unsigned long long msglen, const xmss_params *params); | |||||
int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg,unsigned long long msglen); | |||||
/** | /** | ||||
* Verifies a given message signature pair under a given public key. | * Verifies a given message signature pair under a given public key. | ||||
* | * | ||||
* Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). | * Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). | ||||
*/ | */ | ||||
int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned char *sig_msg,unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params); | |||||
int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned char *sig_msg,unsigned long long sig_msg_len, const unsigned char *pk); | |||||
/* | /* | ||||
* Generates a XMSSMT key pair for a given parameter set. | * Generates a XMSSMT key pair for a given parameter set. | ||||
* Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params); | |||||
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs); | |||||
/** | /** | ||||
* Signs a message. | * Signs a message. | ||||
* Returns | * Returns | ||||
@@ -100,10 +73,10 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsi | |||||
* 2. an updated secret key! | * 2. an updated secret key! | ||||
* | * | ||||
*/ | */ | ||||
int xmssmt_sign(unsigned char *sk, bds_state *state, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params); | |||||
int xmssmt_sign(unsigned char *sk, bds_state *state, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen); | |||||
/** | /** | ||||
* Verifies a given message signature pair under a given public key. | * Verifies a given message signature pair under a given public key. | ||||
*/ | */ | ||||
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params); | |||||
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk); | |||||
#endif | #endif | ||||