diff --git a/.gitignore b/.gitignore index 9c4aad1..c6c2e9a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,12 @@ test/test_xmss test/test_xmss_fast test/test_xmssmt 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/gen_testvectors \ No newline at end of file +test/gen_testvectors +params_XMSS_*.h +params_XMSSMT_*.h +params.h diff --git a/Makefile b/Makefile index eae3e15..c3fdb9c 100644 --- a/Makefile +++ b/Makefile @@ -2,34 +2,45 @@ CC = /usr/bin/gcc CFLAGS = -Wall -g -O3 -Wextra 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 - -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 -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 -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 - -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: -rm *.o *.s -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 \ No newline at end of file diff --git a/params.h.py b/params.h.py new file mode 100644 index 0000000..eceb8c4 --- /dev/null +++ b/params.h.py @@ -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") diff --git a/test/test_wots.c b/test/test_wots.c index 03dbf39..3fb04f7 100644 --- a/test/test_wots.c +++ b/test/test_wots.c @@ -3,6 +3,7 @@ #include #include "../wots.h" #include "../randombytes.h" +#include "../params.h" 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 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 pk2[sig_len]; unsigned char sig[sig_len]; uint32_t addr[8] = {1,2,3,4}; - unsigned char msg[n]; + unsigned char msg[XMSS_N]; 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); - 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++) if (pk1[i] != pk2[i]) { diff --git a/test/test_xmss.c b/test/test_xmss.c index f7bedd2..714f732 100644 --- a/test/test_xmss.c +++ b/test/test_xmss.c @@ -2,6 +2,8 @@ #include #include "../xmss.h" +#include "../params.h" +#include "../randombytes.h" #define MLEN 3491 #define SIGNATURES 50 @@ -13,32 +15,22 @@ unsigned long long mlen; int main() { 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 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 sm[MLEN+signature_length]; - FILE *urandom = fopen("/dev/urandom", "r"); - for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); - printf("keypair\n"); - xmss_keypair(pk, sk, params); + xmss_keypair(pk, 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 @@ -46,17 +38,24 @@ int main() if (idx) printf("\nidx != 0 %lu\n",idx); for (i = 0; i < SIGNATURES; i++) { + randombytes(mi, MLEN); + 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]; printf("\nidx = %lu\n",idx); + for (j = 0; j < smlen; j++) { + printf("%02X", sm[j]); + } + printf("\n"); + r = memcmp(mi, sm+signature_length,MLEN); printf("%d\n", r); /* Test valid signature */ 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); if (r != 0) errors++; r = memcmp(mi,mo,MLEN); @@ -65,7 +64,7 @@ int main() /* Test with modified message */ 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -76,7 +75,7 @@ int main() /* Modified index */ sm[signature_length+10] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -86,7 +85,7 @@ int main() /* Modified R */ sm[2] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -96,7 +95,7 @@ int main() /* Modified OTS sig */ sm[5] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -106,7 +105,7 @@ int main() /* Modified AUTH */ sm[240] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -115,7 +114,6 @@ int main() } printf("#errors = %lu\n", errors); - fclose(urandom); return 0; } diff --git a/test/test_xmss_fast.c b/test/test_xmss_fast.c index d983c2b..e6cf829 100644 --- a/test/test_xmss_fast.c +++ b/test/test_xmss_fast.c @@ -3,14 +3,12 @@ #include #include "../xmss_fast.h" +#include "../params.h" +#include "../randombytes.h" #define MLEN 3491 #define SIGNATURES 256 -unsigned char mi[MLEN]; -unsigned long long smlen; -unsigned long long mlen; - unsigned long long t1, t2; unsigned long long cpucycles(void) @@ -24,55 +22,48 @@ int main() { int r; 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 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? - unsigned char stack[(h+1)*n]; + unsigned char stack[(XMSS_TREEHEIGHT+1)*XMSS_N]; 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 *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); - 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 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"); t1 = cpucycles(); - xmss_keypair(pk, sk, state, params); + xmss_keypair(pk, sk, state); t2 = cpucycles(); printf("cycles = %llu\n", (t2-t1)); double sec = (t2-t1)/3500000; printf("ms = %f\n", sec); - int read; - read = fgetc(stdin); // 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 @@ -81,7 +72,7 @@ int main() for (i = 0; i < SIGNATURES; i++) { 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]; printf("\nidx = %lu\n",idx); @@ -90,7 +81,7 @@ int main() /* Test valid signature */ 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); if (r != 0) errors++; r = memcmp(mi,mo,MLEN); @@ -99,7 +90,7 @@ int main() /* Test with modified message */ 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -110,7 +101,7 @@ int main() /* Modified index */ sm[signature_length+10] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -120,7 +111,7 @@ int main() /* Modified R */ sm[2] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -130,7 +121,7 @@ int main() /* Modified OTS sig */ sm[5] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -140,7 +131,7 @@ int main() /* Modified AUTH */ sm[240] ^= 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); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -150,7 +141,5 @@ int main() printf("#errors = %lu\n", errors); printf("finished loop\n"); - fclose(urandom); - printf("closed urandom\n"); return 0; } diff --git a/test/test_xmssmt.c b/test/test_xmssmt.c index 29827bb..ef79b4e 100644 --- a/test/test_xmssmt.c +++ b/test/test_xmssmt.c @@ -2,9 +2,11 @@ #include #include "../xmss.h" +#include "../params.h" +#include "../randombytes.h" #define MLEN 3491 -#define SIGNATURES 1024 +#define SIGNATURES 5 unsigned char mi[MLEN]; unsigned long long smlen; @@ -14,35 +16,24 @@ int main() { int r; 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 sm[MLEN+signature_length]; - FILE *urandom = fopen("/dev/urandom", "r"); - for (i = 0; i < MLEN; i++) mi[i] = fgetc(urandom); - printf("keypair\n"); - xmssmt_keypair(pk, sk, params); + xmssmt_keypair(pk, 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"); - unsigned int idx_len = params->index_len; + unsigned int idx_len = XMSS_INDEX_LEN; // check index unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { @@ -52,8 +43,10 @@ int main() if (idx) printf("\nidx != 0: %llu\n",idx); for (i = 0; i < SIGNATURES; i++) { + randombytes(mi, MLEN); + printf("sign\n"); - xmssmt_sign(sk, sm, &smlen, mi, MLEN, params); + xmssmt_sign(sk, sm, &smlen, mi, MLEN); idx = 0; for (j = 0; j < idx_len; 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); printf("%d\n", r); + for (j = 0; j < smlen; j++) { + printf("%02X", sm[j]); + } + printf("\n"); + /* Test valid signature */ 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); r = memcmp(mi,mo,MLEN); printf("%d\n", r); @@ -72,7 +70,7 @@ int main() /* Test with modified message */ 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); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); @@ -82,13 +80,12 @@ int main() sm[260] ^= 1; sm[52] ^= 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); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); printf("%llu\n", mlen+1); } - fclose(urandom); return 0; } diff --git a/test/test_xmssmt_fast.c b/test/test_xmssmt_fast.c index fc0f057..0258a16 100644 --- a/test/test_xmssmt_fast.c +++ b/test/test_xmssmt_fast.c @@ -2,29 +2,33 @@ #include #include "../xmss_fast.h" +#include "../params.h" +#include "../randombytes.h" #define MLEN 3491 -#define SIGNATURES 4096 +#define SIGNATURES 128 unsigned char mi[MLEN]; unsigned long long smlen; 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 r; 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; @@ -36,7 +40,7 @@ int main() treehash_inst treehash[(2*d-1) * (tree_h-k)]; unsigned char th_nodes[(2*d-1) * (tree_h-k)*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' 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 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 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"); - xmssmt_keypair(pk, sk, states, wots_sigs, params); + xmssmt_keypair(pk, sk, states, wots_sigs); // 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); + 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"); - unsigned int idx_len = params->index_len; + unsigned int idx_len = XMSS_INDEX_LEN; // check index unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { @@ -83,7 +86,10 @@ int main() for (i = 0; i < SIGNATURES; i++) { 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; for (j = 0; j < idx_len; j++) { @@ -95,7 +101,10 @@ int main() /* Test valid signature */ 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); r = memcmp(mi,mo,MLEN); printf("%d\n", r); @@ -103,7 +112,7 @@ int main() /* Test with modified message */ 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); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); @@ -113,13 +122,12 @@ int main() sm[260] ^= 1; sm[52] ^= 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); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); printf("%llu\n", mlen+1); } - fclose(urandom); return 0; } diff --git a/wots.c b/wots.c index 52b3712..559a21e 100644 --- a/wots.c +++ b/wots.c @@ -14,31 +14,20 @@ Public domain. #include "hash.h" #include "wots.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 * Expands an n-byte array into a len*n byte array * 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; unsigned char ctr[32]; - for(i = 0; i < params->len; i++){ + for(i = 0; i < XMSS_WOTS_LEN; i++){ 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 * 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; - for (j = 0; j < params->n; j++) + for (j = 0; j < XMSS_N; 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); - 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 out = 0; @@ -80,84 +69,84 @@ static void base_w(int *output, const int out_len, const unsigned char *input, c in++; 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++; } } -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; - 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); - 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; 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]; 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); - 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; 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]; 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); - 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); } } diff --git a/wots.h b/wots.h index 6e5c8f7..a7e6e22 100644 --- a/wots.h +++ b/wots.h @@ -10,50 +10,24 @@ Public domain. #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. * 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. */ -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". - * + * */ -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. - * + * */ -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 diff --git a/xmss.c b/xmss.c index 966f2c3..e2dadf7 100644 --- a/xmss.c +++ b/xmss.c @@ -17,89 +17,54 @@ Public domain. //#include "prg.h" #include "xmss_commons.h" #include "hash_address.h" +#include "params.h" // For testing #include "stdio.h" - /** * Used for pseudorandom keygeneration, * 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]; // 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 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. */ -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 height = 0; uint32_t bound; //ADRS.setTreeHeight(0); setTreeHeight(addr, height); - + while (l > 1) { bound = l >> 1; //floor(l / 2); for (i = 0; i < bound; i++) { //ADRS.setTreeIndex(i); setTreeIndex(addr, i); //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 & 1) { //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=(l>>1)+1; } @@ -112,21 +77,21 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param setTreeHeight(addr, height); } //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. */ -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. * */ -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; - uint16_t n = params->n; // use three different addresses because at this point we use all three formats in parallel uint32_t ots_addr[8]; uint32_t ltree_addr[8]; - uint32_t node_addr[8]; + uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots @@ -153,7 +116,7 @@ static void treehash(unsigned char *node, uint16_t height, uint32_t index, const setType(node_addr, 2); uint32_t lastnode, i; - unsigned char stack[(height+1)*n]; + unsigned char stack[(height+1)*XMSS_N]; uint16_t stacklevels[height+1]; 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++) { setLtreeADRS(ltree_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; stackoffset++; while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { setTreeHeight(node_addr, stacklevels[stackoffset-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]++; stackoffset--; } } - for (i=0; i < n; i++) + for (i=0; i < XMSS_N; i++) node[i] = stack[i]; } /** * 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; - 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. // Otherwise, it is the other way around 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]; } else { - for (j = 0; j < n; j++) + for (j = 0; j < XMSS_N; 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); leafidx >>= 1; setTreeIndex(addr, leafidx); 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]; } 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; 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. * 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 n = params->n; - uint32_t h = params->h; - unsigned char tree[2*(1< 1; i>>=1) { + for (i = (1< 1; i>>=1) { setTreeHeight(node_addr, level); // Inner loop: for each pair of sibling nodes for (j = 0; j < i; j+=2) { 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++; } // copy authpath - for (i=0; i < h; i++) - memcpy(authpath + i*n, tree + ((1<>i)*n + ((leaf_idx >> i) ^ 1) * n, n); + for (i=0; i < XMSS_TREEHEIGHT; i++) + memcpy(authpath + i*XMSS_N, tree + ((1<>i)*XMSS_N + ((leaf_idx >> i) ^ 1) * XMSS_N, XMSS_N); // 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 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 sk[0] = 0; sk[1] = 0; sk[2] = 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 - 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}; // 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 - memcpy(sk+4+3*n, pk, n); + memcpy(sk+4+3*XMSS_N, pk, XMSS_N); return 0; } @@ -313,26 +271,25 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params) * 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; // Extract SK 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 unsigned char idx_bytes_32[32]; to_byte(idx_bytes_32, idx, 32); - unsigned char hash_key[3*n]; + unsigned char hash_key[3*XMSS_N]; // Update SK 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! // 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}; // --------------------------------- @@ -355,13 +312,13 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig // Message Hash: // 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) - 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 - 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 *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; // Copy R to signature - for (i = 0; i < n; i++) + for (i = 0; i < XMSS_N; 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" @@ -391,17 +348,17 @@ int xmss_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig setOTSADRS(ots_addr, idx); // 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 - 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? //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. */ -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 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 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); // 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 - 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; - 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 @@ -464,22 +420,22 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne // Prepare Address setOTSADRS(ots_addr, idx); // 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 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 - 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]) goto fail; @@ -503,26 +459,25 @@ fail: * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] * 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; // Set idx = 0 - for (i = 0; i < params->index_len; i++) { + for (i = 0; i < XMSS_INDEX_LEN; i++) { 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 - 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 uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - setLayerADRS(addr, (params->d-1)); + setLayerADRS(addr, (XMSS_D-1)); // 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; } @@ -533,40 +488,37 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params) * 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; uint32_t idx_leaf; 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 - 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}; unsigned char idx_bytes_32[32]; // Extract SK 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 - 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. // -- 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: // First compute pseudorandom value 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) - 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 - 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 *sig_msg_len = 0; // 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 - for (i=0; i < n; i++) + for (i=0; i < XMSS_N; 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" @@ -614,47 +566,47 @@ int xmssmt_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *s // Prepare Address 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); setTreeADRS(ots_addr, idx_tree); setOTSADRS(ots_addr, idx_leaf); // 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 - 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... unsigned int j; - for (j = 1; j < params->d; j++) { + for (j = 1; j < XMSS_D; j++) { // 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); setTreeADRS(ots_addr, idx_tree); setOTSADRS(ots_addr, idx_leaf); // 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 - 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? @@ -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. */ -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; uint32_t idx_leaf; unsigned long long i, m_len; 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 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}; // 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); - 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) - 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 - 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; - 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 - 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); setTreeADRS(ots_addr, idx_tree); 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); // 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 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 - 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 - 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); 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); // 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 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 - 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]) goto fail; diff --git a/xmss.h b/xmss.h index a51c2b8..ce7fdc3 100644 --- a/xmss.h +++ b/xmss.h @@ -15,37 +15,12 @@ typedef struct{ unsigned int subleaf; } 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. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * 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. * Returns @@ -53,20 +28,20 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, xmss_params *params); * 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. * * 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. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * 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. * Returns @@ -74,10 +49,10 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, xmssmt_params *params); * 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. */ -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 diff --git a/xmss_fast.c b/xmss_fast.c index 53e146d..2dd8732 100644 --- a/xmss_fast.c +++ b/xmss_fast.c @@ -17,10 +17,7 @@ Public domain. #include "xmss_commons.h" #include "hash_address.h" -// For testing -#include "stdio.h" - - +#include "params.h" /** * Used for pseudorandom keygeneration, @@ -40,26 +37,6 @@ static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, u prf(seed, bytes, sk_seed, n); } -/** - * Initialize xmss params struct - * parameter names are the same as in the draft - * parameter k is K as used in the BDS algorithm - */ -int xmss_set_params(xmss_params *params, int n, int h, int w, int k) -{ - if (k >= h || k < 2 || (h - k) % 2) { - fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n"); - return 1; - } - params->h = h; - params->n = n; - params->k = k; - wots_params wots_par; - wots_set_params(&wots_par, n, w); - params->wots_par = wots_par; - return 0; -} - /** * Initialize BDS state struct * parameter names are the same as used in the description of the BDS traversal @@ -76,37 +53,13 @@ void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, state->next_leaf = next_leaf; } -/** - * 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) -{ - if (h % d) { - fprintf(stderr, "d must divide h without remainder!\n"); - return 1; - } - params->h = h; - params->d = d; - params->n = n; - params->index_len = (h + 7) / 8; - xmss_params xmss_par; - if (xmss_set_params(&xmss_par, n, (h/d), w, k)) { - return 1; - } - params->xmss_par = xmss_par; - return 0; -} - /** * 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; + unsigned int n = XMSS_N; uint32_t i = 0; uint32_t height = 0; uint32_t bound; @@ -144,19 +97,19 @@ static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_param /** * 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, XMSS_N, 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); } -static int treehash_minheight_on_stack(bds_state* state, const xmss_params *params, const treehash_inst *treehash) { - unsigned int r = params->h, i; +static int treehash_minheight_on_stack(bds_state* state, const treehash_inst *treehash) { + unsigned int r = XMSS_TREEHEIGHT, i; for (i = 0; i < treehash->stackusage; i++) { if (state->stacklevels[state->stackoffset - i - 1] < r) { r = state->stacklevels[state->stackoffset - i - 1]; @@ -170,16 +123,13 @@ static int treehash_minheight_on_stack(bds_state* state, const xmss_params *para * Currently only used for key generation. * */ -static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) +static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) { unsigned int idx = index; - unsigned int n = params->n; - unsigned int h = params->h; - unsigned int k = params->k; // use three different addresses because at this point we use all three formats in parallel uint32_t ots_addr[8]; uint32_t ltree_addr[8]; - uint32_t node_addr[8]; + uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots @@ -190,14 +140,14 @@ static void treehash_setup(unsigned char *node, int height, int index, bds_state setType(node_addr, 2); uint32_t lastnode, i; - unsigned char stack[(height+1)*n]; + unsigned char stack[(height+1)*XMSS_N]; unsigned int stacklevels[height+1]; unsigned int stackoffset=0; unsigned int nodeh; lastnode = idx+(1<treehash[i].h = i; state->treehash[i].completed = 1; state->treehash[i].stackusage = 0; @@ -207,46 +157,44 @@ static void treehash_setup(unsigned char *node, int height, int index, bds_state for (; idx < lastnode; idx++) { setLtreeADRS(ltree_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; stackoffset++; - if (h - k > 0 && i == 3) { - memcpy(state->treehash[0].node, stack+stackoffset*n, n); + if (XMSS_TREEHEIGHT - XMSS_BDS_K > 0 && i == 3) { + memcpy(state->treehash[0].node, stack+stackoffset*XMSS_N, XMSS_N); } while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { nodeh = stacklevels[stackoffset-1]; if (i >> nodeh == 1) { - memcpy(state->auth + nodeh*n, stack+(stackoffset-1)*n, n); + memcpy(state->auth + nodeh*XMSS_N, stack+(stackoffset-1)*XMSS_N, XMSS_N); } else { - if (nodeh < h - k && i >> nodeh == 3) { - memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*n, n); + if (nodeh < XMSS_TREEHEIGHT - XMSS_BDS_K && i >> nodeh == 3) { + memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*XMSS_N, XMSS_N); } - else if (nodeh >= h - k) { - memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n); + else if (nodeh >= XMSS_TREEHEIGHT - XMSS_BDS_K) { + memcpy(state->retain + ((1 << (XMSS_TREEHEIGHT - 1 - nodeh)) + nodeh - XMSS_TREEHEIGHT + (((i >> nodeh) - 3) >> 1)) * XMSS_N, stack+(stackoffset-1)*XMSS_N, XMSS_N); } } setTreeHeight(node_addr, stacklevels[stackoffset-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]++; stackoffset--; } i++; } - for (i = 0; i < n; i++) + for (i = 0; i < XMSS_N; i++) node[i] = stack[i]; } -static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { - int n = params->n; - +static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) { uint32_t ots_addr[8]; uint32_t ltree_addr[8]; - uint32_t node_addr[8]; + uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots @@ -259,25 +207,25 @@ static void treehash_update(treehash_inst *treehash, bds_state *state, const uns setLtreeADRS(ltree_addr, treehash->next_idx); setOTSADRS(ots_addr, treehash->next_idx); - unsigned char nodebuffer[2 * n]; + unsigned char nodebuffer[2 * XMSS_N]; unsigned int nodeheight = 0; - gen_leaf_wots(nodebuffer, sk_seed, params, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(nodebuffer, sk_seed, pub_seed, ltree_addr, ots_addr); while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) { - memcpy(nodebuffer + n, nodebuffer, n); - memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n); + memcpy(nodebuffer + XMSS_N, nodebuffer, XMSS_N); + memcpy(nodebuffer, state->stack + (state->stackoffset-1)*XMSS_N, XMSS_N); setTreeHeight(node_addr, nodeheight); setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1))); - hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n); + hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, XMSS_N); nodeheight++; treehash->stackusage--; state->stackoffset--; } if (nodeheight == treehash->h) { // this also implies stackusage == 0 - memcpy(treehash->node, nodebuffer, n); + memcpy(treehash->node, nodebuffer, XMSS_N); treehash->completed = 1; } else { - memcpy(state->stack + state->stackoffset*n, nodebuffer, n); + memcpy(state->stack + state->stackoffset*XMSS_N, nodebuffer, XMSS_N); treehash->stackusage++; state->stacklevels[state->stackoffset] = nodeheight; state->stackoffset++; @@ -288,84 +236,80 @@ static void treehash_update(treehash_inst *treehash, bds_state *state, const uns /** * 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; - 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. // Otherwise, it is the other way around 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]; } else { - for (j = 0; j < n; j++) + for (j = 0; j < XMSS_N; 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); leafidx >>= 1; setTreeIndex(addr, leafidx); 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]; } 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; setTreeIndex(addr, leafidx); - hash_h(root, buffer, pub_seed, addr, n); + hash_h(root, buffer, pub_seed, addr, XMSS_N); } /** * Performs one treehash update on the instance that needs it the most. * Returns 1 if such an instance was not found **/ -static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { +static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, unsigned char *pub_seed, const uint32_t addr[8]) { uint32_t i, j; unsigned int level, l_min, low; - unsigned int h = params->h; - unsigned int k = params->k; unsigned int used = 0; for (j = 0; j < updates; j++) { - l_min = h; - level = h - k; - for (i = 0; i < h - k; i++) { + l_min = XMSS_TREEHEIGHT; + level = XMSS_TREEHEIGHT - XMSS_BDS_K; + for (i = 0; i < XMSS_TREEHEIGHT - XMSS_BDS_K; i++) { if (state->treehash[i].completed) { - low = h; + low = XMSS_TREEHEIGHT; } else if (state->treehash[i].stackusage == 0) { low = i; } else { - low = treehash_minheight_on_stack(state, params, &(state->treehash[i])); + low = treehash_minheight_on_stack(state, &(state->treehash[i])); } if (low < l_min) { level = i; l_min = low; } } - if (level == h - k) { + if (level == XMSS_TREEHEIGHT - XMSS_BDS_K) { break; } - treehash_update(&(state->treehash[level]), state, sk_seed, params, pub_seed, addr); + treehash_update(&(state->treehash[level]), state, sk_seed, pub_seed, addr); used++; } return updates - used; @@ -375,18 +319,14 @@ static char bds_treehash_update(bds_state *state, unsigned int updates, const un * Updates the state (typically NEXT_i) by adding a leaf and updating the stack * Returns 1 if all leaf nodes have already been processed **/ -static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { +static char bds_state_update(bds_state *state, const unsigned char *sk_seed, unsigned char *pub_seed, const uint32_t addr[8]) { uint32_t ltree_addr[8]; uint32_t node_addr[8]; uint32_t ots_addr[8]; - int n = params->n; - int h = params->h; - int k = params->k; - int nodeh; int idx = state->next_leaf; - if (idx == 1 << h) { + if (idx == 1 << XMSS_TREEHEIGHT) { return 1; } @@ -402,29 +342,29 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, con setOTSADRS(ots_addr, idx); setLtreeADRS(ltree_addr, idx); - gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(state->stack+state->stackoffset*XMSS_N, sk_seed, pub_seed, ltree_addr, ots_addr); state->stacklevels[state->stackoffset] = 0; state->stackoffset++; - if (h - k > 0 && idx == 3) { - memcpy(state->treehash[0].node, state->stack+state->stackoffset*n, n); + if (XMSS_TREEHEIGHT - XMSS_BDS_K > 0 && idx == 3) { + memcpy(state->treehash[0].node, state->stack+state->stackoffset*XMSS_N, XMSS_N); } while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) { nodeh = state->stacklevels[state->stackoffset-1]; if (idx >> nodeh == 1) { - memcpy(state->auth + nodeh*n, state->stack+(state->stackoffset-1)*n, n); + memcpy(state->auth + nodeh*XMSS_N, state->stack+(state->stackoffset-1)*XMSS_N, XMSS_N); } else { - if (nodeh < h - k && idx >> nodeh == 3) { - memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*n, n); + if (nodeh < XMSS_TREEHEIGHT - XMSS_BDS_K && idx >> nodeh == 3) { + memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*XMSS_N, XMSS_N); } - else if (nodeh >= h - k) { - memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n); + else if (nodeh >= XMSS_TREEHEIGHT - XMSS_BDS_K) { + memcpy(state->retain + ((1 << (XMSS_TREEHEIGHT - 1 - nodeh)) + nodeh - XMSS_TREEHEIGHT + (((idx >> nodeh) - 3) >> 1)) * XMSS_N, state->stack+(state->stackoffset-1)*XMSS_N, XMSS_N); } } setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]); setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); - hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n); + hash_h(state->stack+(state->stackoffset-2)*XMSS_N, state->stack+(state->stackoffset-2)*XMSS_N, pub_seed, node_addr, XMSS_N); state->stacklevels[state->stackoffset-2]++; state->stackoffset--; @@ -438,21 +378,17 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, con * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo * in "Post Quantum Cryptography", Springer 2009. */ -static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8]) +static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, unsigned char *pub_seed, uint32_t addr[8]) { unsigned int i; - unsigned int n = params->n; - unsigned int h = params->h; - unsigned int k = params->k; - - unsigned int tau = h; + unsigned int tau = XMSS_TREEHEIGHT; unsigned int startidx; unsigned int offset, rowidx; - unsigned char buf[2 * n]; + unsigned char buf[2 * XMSS_N]; uint32_t ots_addr[8]; uint32_t ltree_addr[8]; - uint32_t node_addr[8]; + uint32_t node_addr[8]; // only copy layer and tree address parts memcpy(ots_addr, addr, 12); // type = ots @@ -462,7 +398,7 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsi memcpy(node_addr, addr, 12); setType(node_addr, 2); - for (i = 0; i < h; i++) { + for (i = 0; i < XMSS_TREEHEIGHT; i++) { if (! ((leaf_idx >> i) & 1)) { tau = i; break; @@ -470,36 +406,36 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsi } if (tau > 0) { - memcpy(buf, state->auth + (tau-1) * n, n); + memcpy(buf, state->auth + (tau-1) * XMSS_N, XMSS_N); // we need to do this before refreshing state->keep to prevent overwriting - memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n); + memcpy(buf + XMSS_N, state->keep + ((tau-1) >> 1) * XMSS_N, XMSS_N); } - if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) { - memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n); + if (!((leaf_idx >> (tau + 1)) & 1) && (tau < XMSS_TREEHEIGHT - 1)) { + memcpy(state->keep + (tau >> 1)*XMSS_N, state->auth + tau*XMSS_N, XMSS_N); } if (tau == 0) { setLtreeADRS(ltree_addr, leaf_idx); setOTSADRS(ots_addr, leaf_idx); - gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(state->auth, sk_seed, pub_seed, ltree_addr, ots_addr); } else { setTreeHeight(node_addr, (tau-1)); setTreeIndex(node_addr, leaf_idx >> tau); - hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n); + hash_h(state->auth + tau * XMSS_N, buf, pub_seed, node_addr, XMSS_N); for (i = 0; i < tau; i++) { - if (i < h - k) { - memcpy(state->auth + i * n, state->treehash[i].node, n); + if (i < XMSS_TREEHEIGHT - XMSS_BDS_K) { + memcpy(state->auth + i * XMSS_N, state->treehash[i].node, XMSS_N); } else { - offset = (1 << (h - 1 - i)) + i - h; + offset = (1 << (XMSS_TREEHEIGHT - 1 - i)) + i - XMSS_TREEHEIGHT; rowidx = ((leaf_idx >> i) - 1) >> 1; - memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n); + memcpy(state->auth + i * XMSS_N, state->retain + (offset + rowidx) * XMSS_N, XMSS_N); } } - for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) { + for (i = 0; i < ((tau < XMSS_TREEHEIGHT - XMSS_BDS_K) ? tau : (XMSS_TREEHEIGHT - XMSS_BDS_K)); i++) { startidx = leaf_idx + 1 + 3 * (1 << i); - if (startidx < 1U << h) { + if (startidx < 1U << XMSS_TREEHEIGHT) { state->treehash[i].h = i; state->treehash[i].next_idx = startidx; state->treehash[i].completed = 0; @@ -514,25 +450,24 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsi * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * 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) { - unsigned int n = params->n; // Set idx = 0 sk[0] = 0; sk[1] = 0; sk[2] = 0; sk[3] = 0; // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) - randombytes(sk+4, 3*n); + randombytes(sk+4, 3*XMSS_N); // 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}; // Compute root - treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr); + treehash_setup(pk, XMSS_TREEHEIGHT, 0, state, sk+4, sk+4+2*XMSS_N, addr); // copy root to sk - memcpy(sk+4+3*n, pk, n); + memcpy(sk+4+3*XMSS_N, pk, XMSS_N); return 0; } @@ -543,27 +478,24 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_pa * 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) { - unsigned int h = params->h; - unsigned int n = params->n; - unsigned int k = params->k; uint16_t i = 0; // Extract SK unsigned long 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 unsigned char idx_bytes_32[32]; to_byte(idx_bytes_32, idx, 32); - unsigned char hash_key[3*n]; + unsigned char hash_key[3*XMSS_N]; // Update SK sk[0] = ((idx + 1) >> 24) & 255; @@ -574,9 +506,9 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // Init working params - unsigned char R[n]; - unsigned char msg_h[n]; - unsigned char ots_seed[n]; + unsigned char R[XMSS_N]; + unsigned char msg_h[XMSS_N]; + unsigned char ots_seed[XMSS_N]; uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // --------------------------------- @@ -585,13 +517,13 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig // Message Hash: // 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) - 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 - 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 *sig_msg_len = 0; @@ -606,11 +538,11 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig *sig_msg_len += 4; // Copy R to signature - for (i = 0; i < n; i++) + for (i = 0; i < XMSS_N; 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" @@ -621,27 +553,24 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig setOTSADRS(ots_addr, idx); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, n, ots_addr); + get_seed(ots_seed, sk_seed, XMSS_N, ots_addr); // 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; // the auth path was already computed during the previous round - memcpy(sig_msg, state->auth, h*n); + memcpy(sig_msg, state->auth, XMSS_TREEHEIGHT*XMSS_N); - if (idx < (1U << h) - 1) { - bds_round(state, idx, sk_seed, params, pub_seed, ots_addr); - bds_treehash_update(state, (h - k) >> 1, sk_seed, params, pub_seed, ots_addr); + if (idx < (1U << XMSS_TREEHEIGHT) - 1) { + bds_round(state, idx, sk_seed, pub_seed, ots_addr); + bds_treehash_update(state, (XMSS_TREEHEIGHT - XMSS_BDS_K) >> 1, sk_seed, pub_seed, ots_addr); } - sig_msg += params->h*n; - *sig_msg_len += params->h*n; - - //Whipe secret elements? - //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); + sig_msg += XMSS_TREEHEIGHT*XMSS_N; + *sig_msg_len += XMSS_TREEHEIGHT*XMSS_N; memcpy(sig_msg, msg, msglen); *sig_msg_len += msglen; @@ -652,20 +581,18 @@ int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsig /** * 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) { - unsigned int n = params->n; - unsigned long long i, m_len; 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 uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -678,20 +605,19 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne // Extract index idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; - printf("verify:: idx = %lu\n", 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 - 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; - 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 @@ -700,22 +626,22 @@ int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigne // Prepare Address setOTSADRS(ots_addr, idx); // 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 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 - 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]) goto fail; @@ -739,34 +665,33 @@ fail: * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * 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) { - unsigned int n = params->n; - unsigned int i; - unsigned char ots_seed[params->n]; + unsigned char ots_seed[XMSS_N]; + int i; // Set idx = 0 - for (i = 0; i < params->index_len; i++) { + for (i = 0; i < XMSS_INDEX_LEN; i++) { 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 - memcpy(pk+n, sk+params->index_len+2*n, n); + memcpy(pk+XMSS_N, sk+XMSS_INDEX_LEN+2*XMSS_N, XMSS_N); uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Start with the bottom-most layer setLayerADRS(addr, 0); // Set up state and compute wots signatures for all but topmost tree root - for (i = 0; i < params->d - 1; i++) { + for (i = 0; i < XMSS_D - 1; i++) { // Compute seed for OTS key pair - treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); + treehash_setup(pk, XMSS_TREEHEIGHT, 0, states + i, sk+XMSS_INDEX_LEN, pk+XMSS_N, addr); setLayerADRS(addr, (i+1)); - get_seed(ots_seed, sk+params->index_len, n, addr); - wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr); + get_seed(ots_seed, sk+XMSS_INDEX_LEN, XMSS_N, addr); + wots_sign(wots_sigs + i*XMSS_WOTS_KEYSIZE, pk, ots_seed, pk+XMSS_N, addr); } // Address now points to the single tree on layer d-1 - treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); - memcpy(sk+params->index_len+3*n, pk, n); + treehash_setup(pk, XMSS_TREEHEIGHT, 0, states + i, sk+XMSS_INDEX_LEN, pk+XMSS_N, addr); + memcpy(sk+XMSS_INDEX_LEN+3*XMSS_N, pk, XMSS_N); return 0; } @@ -777,28 +702,22 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsi * 2. an updated secret key! * */ -int xmssmt_sign(unsigned char *sk, bds_state *states, 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 *states, unsigned char *wots_sigs, 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 h = params->h; - unsigned int k = params->xmss_par.k; - unsigned int idx_len = params->index_len; uint64_t idx_tree; uint32_t idx_leaf; uint64_t i, j; int needswap_upto = -1; unsigned int updates; - 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 - unsigned char R[n]; - unsigned char msg_h[n]; - unsigned char hash_key[3*n]; - unsigned char ots_seed[n]; + unsigned char R[XMSS_N]; + unsigned char msg_h[XMSS_N]; + unsigned char hash_key[3*XMSS_N]; + unsigned char ots_seed[XMSS_N]; uint32_t 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]; @@ -806,17 +725,17 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, // Extract SK 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 - 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. // -- A productive implementation should use a file handle instead and write the updated secret key at this point! @@ -829,32 +748,32 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, // Message Hash: // First compute pseudorandom value 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) - 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 - 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 *sig_msg_len = 0; // 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 - for (i = 0; i < n; i++) + for (i = 0; i < XMSS_N; 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" @@ -864,93 +783,90 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, // Prepare Address 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); setTreeADRS(ots_addr, idx_tree); setOTSADRS(ots_addr, idx_leaf); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, n, ots_addr); + get_seed(ots_seed, sk_seed, XMSS_N, ots_addr); // 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; - memcpy(sig_msg, states[0].auth, tree_h*n); - sig_msg += tree_h*n; - *sig_msg_len += tree_h*n; + memcpy(sig_msg, states[0].auth, XMSS_TREEHEIGHT*XMSS_N); + sig_msg += XMSS_TREEHEIGHT*XMSS_N; + *sig_msg_len += XMSS_TREEHEIGHT*XMSS_N; // prepare signature of remaining layers - for (i = 1; i < params->d; i++) { + for (i = 1; i < XMSS_D; i++) { // put WOTS signature in place - memcpy(sig_msg, wots_sigs + (i-1)*params->xmss_par.wots_par.keysize, params->xmss_par.wots_par.keysize); + memcpy(sig_msg, wots_sigs + (i-1)*XMSS_WOTS_KEYSIZE, XMSS_WOTS_KEYSIZE); - 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; // put AUTH nodes in place - memcpy(sig_msg, states[i].auth, tree_h*n); - sig_msg += tree_h*n; - *sig_msg_len += tree_h*n; + memcpy(sig_msg, states[i].auth, XMSS_TREEHEIGHT*XMSS_N); + sig_msg += XMSS_TREEHEIGHT*XMSS_N; + *sig_msg_len += XMSS_TREEHEIGHT*XMSS_N; } - updates = (tree_h - k) >> 1; + updates = (XMSS_TREEHEIGHT - XMSS_BDS_K) >> 1; setTreeADRS(addr, (idx_tree + 1)); // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists - if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) { - bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr); + if ((1 + idx_tree) * (1 << XMSS_TREEHEIGHT) + idx_leaf < (1ULL << XMSS_FULLHEIGHT)) { + bds_state_update(&states[XMSS_D], sk_seed, pub_seed, addr); } - for (i = 0; i < params->d; i++) { + for (i = 0; i < XMSS_D; i++) { // check if we're not at the end of a tree - if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) { - idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1); - idx_tree = (idx >> (tree_h * (i+1))); + if (! (((idx + 1) & ((1ULL << ((i+1)*XMSS_TREEHEIGHT)) - 1)) == 0)) { + idx_leaf = (idx >> (XMSS_TREEHEIGHT * i)) & ((1 << XMSS_TREEHEIGHT)-1); + idx_tree = (idx >> (XMSS_TREEHEIGHT * (i+1))); setLayerADRS(addr, i); setTreeADRS(addr, idx_tree); if (i == (unsigned int) (needswap_upto + 1)) { - bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr); + bds_round(&states[i], idx_leaf, sk_seed, pub_seed, addr); } - updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr); + updates = bds_treehash_update(&states[i], updates, sk_seed, pub_seed, addr); setTreeADRS(addr, (idx_tree + 1)); // if a NEXT-tree exists for this level; - if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) { - if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) { - bds_state_update(&states[params->d + i], sk_seed, &(params->xmss_par), pub_seed, addr); + if ((1 + idx_tree) * (1 << XMSS_TREEHEIGHT) + idx_leaf < (1ULL << (XMSS_FULLHEIGHT - XMSS_TREEHEIGHT * i))) { + if (i > 0 && updates > 0 && states[XMSS_D + i].next_leaf < (1ULL << XMSS_FULLHEIGHT)) { + bds_state_update(&states[XMSS_D + i], sk_seed, pub_seed, addr); updates--; } } } - else if (idx < (1ULL << h) - 1) { - memcpy(&tmp, states+params->d + i, sizeof(bds_state)); - memcpy(states+params->d + i, states + i, sizeof(bds_state)); + else if (idx < (1ULL << XMSS_FULLHEIGHT) - 1) { + memcpy(&tmp, states+XMSS_D + i, sizeof(bds_state)); + memcpy(states+XMSS_D + i, states + i, sizeof(bds_state)); memcpy(states + i, &tmp, sizeof(bds_state)); setLayerADRS(ots_addr, (i+1)); - setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h))); - setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1))); + setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * XMSS_TREEHEIGHT))); + setOTSADRS(ots_addr, (((idx >> ((i+1) * XMSS_TREEHEIGHT)) + 1) & ((1 << XMSS_TREEHEIGHT)-1))); - get_seed(ots_seed, sk+params->index_len, n, ots_addr); - wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); + get_seed(ots_seed, sk+XMSS_INDEX_LEN, XMSS_N, ots_addr); + wots_sign(wots_sigs + i*XMSS_WOTS_KEYSIZE, states[i].stack, ots_seed, pub_seed, ots_addr); - states[params->d + i].stackoffset = 0; - states[params->d + i].next_leaf = 0; + states[XMSS_D + i].stackoffset = 0; + states[XMSS_D + i].next_leaf = 0; updates--; // WOTS-signing counts as one update needswap_upto = i; - for (j = 0; j < tree_h-k; j++) { + for (j = 0; j < XMSS_TREEHEIGHT-XMSS_BDS_K; j++) { states[i].treehash[j].completed = 1; } } } - //Whipe secret elements? - //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); - memcpy(sig_msg, msg, msglen); *sig_msg_len += msglen; @@ -960,25 +876,21 @@ int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, /** * 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; uint32_t idx_leaf; unsigned long long i, m_len; 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 uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -986,26 +898,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}; // 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); - 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) - 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 (recall, R is now on pole position at sig_msg - 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; - 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); //----------------------- @@ -1013,8 +924,8 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig //----------------------- // 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); setTreeADRS(ots_addr, idx_tree); setType(ots_addr, 0); @@ -1028,25 +939,25 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig setOTSADRS(ots_addr, idx_leaf); // 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 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 - 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 - 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); setTreeADRS(ots_addr, idx_tree); @@ -1061,24 +972,24 @@ int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsig setOTSADRS(ots_addr, idx_leaf); // 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 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 - 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]) goto fail; diff --git a/xmss_fast.h b/xmss_fast.h index 922f908..2e473f8 100644 --- a/xmss_fast.h +++ b/xmss_fast.h @@ -15,21 +15,6 @@ typedef struct{ unsigned int subleaf; } 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{ unsigned int h; unsigned int next_idx; @@ -54,24 +39,12 @@ typedef struct { * 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); -/** - * 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. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * 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. * Returns @@ -79,20 +52,20 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_pa * 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. * * 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. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * 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. * Returns @@ -100,10 +73,10 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsi * 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. */ -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