This starts a cleanup / refactor, but there is still some low-hanging fruit.master
@@ -5,5 +5,12 @@ test/test_xmss | |||
test/test_xmss_fast | |||
test/test_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 | |||
test/gen_testvectors | |||
params_XMSS_*.h | |||
params_XMSSMT_*.h | |||
params.h |
@@ -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 |
@@ -0,0 +1,172 @@ | |||
#! /usr/bin/env python3 | |||
# This script generates params.h files for the XMSS and XMSSMT parameter sets. | |||
# It takes a single parameter, namely the name of the parameter set. | |||
# Its output matches the following parameter tables. | |||
# +-----------------------+-----------+----+----+-----+----+ | |||
# | Name | Functions | n | w | len | h | | |||
# +-----------------------+-----------+----+----+-----+----+ | |||
# | REQUIRED: | | | | | | | |||
# | | | | | | | | |||
# | XMSS_SHA2-256_W16_H10 | SHA2-256 | 32 | 16 | 67 | 10 | | |||
# | | | | | | | | |||
# | XMSS_SHA2-256_W16_H16 | SHA2-256 | 32 | 16 | 67 | 16 | | |||
# | | | | | | | | |||
# | XMSS_SHA2-256_W16_H20 | SHA2-256 | 32 | 16 | 67 | 20 | | |||
# | | | | | | | | |||
# | OPTIONAL: | | | | | | | |||
# | | | | | | | | |||
# | XMSS_SHA2-512_W16_H10 | SHA2-512 | 64 | 16 | 131 | 10 | | |||
# | | | | | | | | |||
# | XMSS_SHA2-512_W16_H16 | SHA2-512 | 64 | 16 | 131 | 16 | | |||
# | | | | | | | | |||
# | XMSS_SHA2-512_W16_H20 | SHA2-512 | 64 | 16 | 131 | 20 | | |||
# | | | | | | | | |||
# | XMSS_SHAKE128_W16_H10 | SHAKE128 | 32 | 16 | 67 | 10 | | |||
# | | | | | | | | |||
# | XMSS_SHAKE128_W16_H16 | SHAKE128 | 32 | 16 | 67 | 16 | | |||
# | | | | | | | | |||
# | XMSS_SHAKE128_W16_H20 | SHAKE128 | 32 | 16 | 67 | 20 | | |||
# | | | | | | | | |||
# | XMSS_SHAKE256_W16_H10 | SHAKE256 | 64 | 16 | 131 | 10 | | |||
# | | | | | | | | |||
# | XMSS_SHAKE256_W16_H16 | SHAKE256 | 64 | 16 | 131 | 16 | | |||
# | | | | | | | | |||
# | XMSS_SHAKE256_W16_H20 | SHAKE256 | 64 | 16 | 131 | 20 | | |||
# +-----------------------+-----------+----+----+-----+----+ | |||
# +-----------------------------+-----------+----+----+-----+----+----+ | |||
# | Name | Functions | n | w | len | h | d | | |||
# +-----------------------------+-----------+----+----+-----+----+----+ | |||
# | REQUIRED: | | | | | | | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H20_D2 | SHA2-256 | 32 | 16 | 67 | 20 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H20_D4 | SHA2-256 | 32 | 16 | 67 | 20 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H40_D2 | SHA2-256 | 32 | 16 | 67 | 40 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H40_D4 | SHA2-256 | 32 | 16 | 67 | 40 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H40_D8 | SHA2-256 | 32 | 16 | 67 | 40 | 8 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H60_D3 | SHA2-256 | 32 | 16 | 67 | 60 | 3 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H60_D6 | SHA2-256 | 32 | 16 | 67 | 60 | 6 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-256_W16_H60_D12 | SHA2-256 | 32 | 16 | 67 | 60 | 12 | | |||
# | | | | | | | | | |||
# | OPTIONAL: | | | | | | | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H20_D2 | SHA2-512 | 64 | 16 | 131 | 20 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H20_D4 | SHA2-512 | 64 | 16 | 131 | 20 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H40_D2 | SHA2-512 | 64 | 16 | 131 | 40 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H40_D4 | SHA2-512 | 64 | 16 | 131 | 40 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H40_D8 | SHA2-512 | 64 | 16 | 131 | 40 | 8 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H60_D3 | SHA2-512 | 64 | 16 | 131 | 60 | 3 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H60_D6 | SHA2-512 | 64 | 16 | 131 | 60 | 6 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHA2-512_W16_H60_D12 | SHA2-512 | 64 | 16 | 131 | 60 | 12 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H20_D2 | SHAKE128 | 32 | 16 | 67 | 20 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H20_D4 | SHAKE128 | 32 | 16 | 67 | 20 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H40_D2 | SHAKE128 | 32 | 16 | 67 | 40 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H40_D4 | SHAKE128 | 32 | 16 | 67 | 40 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H40_D8 | SHAKE128 | 32 | 16 | 67 | 40 | 8 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H60_D3 | SHAKE128 | 32 | 16 | 67 | 60 | 3 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H60_D6 | SHAKE128 | 32 | 16 | 67 | 60 | 6 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE128_W16_H60_D12 | SHAKE128 | 32 | 16 | 67 | 60 | 12 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H20_D2 | SHAKE256 | 64 | 16 | 131 | 20 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H20_D4 | SHAKE256 | 64 | 16 | 131 | 20 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H40_D2 | SHAKE256 | 64 | 16 | 131 | 40 | 2 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H40_D4 | SHAKE256 | 64 | 16 | 131 | 40 | 4 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H40_D8 | SHAKE256 | 64 | 16 | 131 | 40 | 8 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H60_D3 | SHAKE256 | 64 | 16 | 131 | 60 | 3 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H60_D6 | SHAKE256 | 64 | 16 | 131 | 60 | 6 | | |||
# | | | | | | | | | |||
# | XMSSMT_SHAKE256_W16_H60_D12 | SHAKE256 | 64 | 16 | 131 | 60 | 12 | | |||
# +-----------------------------+-----------+----+----+-----+----+----+ | |||
import sys | |||
from math import log2, ceil, floor | |||
if len(sys.argv) != 2: | |||
print("Please supply a parameter identifier.", file=sys.stderr) | |||
sys.exit(1) | |||
param = sys.argv[1].split('_') | |||
print("#ifndef PARAMS_H") | |||
print("#define PARAMS_H") | |||
print("") | |||
print("// This file was automatically generated using params.h.py.") | |||
print("// It matches the parameter set defined as", sys.argv[1], end=".\n") | |||
functions = ["SHA2-256", "SHA2-512", "SHAKE128", "SHAKE256"] | |||
nvalues = { | |||
"SHA2-256": 32, | |||
"SHA2-512": 64, | |||
"SHAKE128": 32, | |||
"SHAKE256": 64, | |||
} | |||
for i, func in enumerate(functions): | |||
print("#define XMSS_{} {}".format(func.replace('-', '_'), i)) | |||
print("#define XMSS_FUNC", functions.index(param[1])) | |||
XMSS_N = int(nvalues[param[1]]) | |||
print("#define XMSS_N", XMSS_N) | |||
XMSS_WOTS_W = int(param[2][1:]) | |||
print("#define XMSS_WOTS_W", XMSS_WOTS_W) | |||
WOTS_LOG_W = int(log2(int(param[2][1:]))) | |||
WOTS_LEN1 = ceil(((8*XMSS_N) / WOTS_LOG_W)) | |||
WOTS_LEN2 = floor(log2(WOTS_LEN1*(XMSS_WOTS_W-1)) / WOTS_LOG_W) + 1 | |||
print("#define XMSS_WOTS_LOG_W", WOTS_LOG_W) | |||
print("#define XMSS_WOTS_LEN1", WOTS_LEN1) | |||
print("#define XMSS_WOTS_LEN2", WOTS_LEN2) | |||
print("#define XMSS_WOTS_LEN", WOTS_LEN1 + WOTS_LEN2) | |||
WOTS_KEYSIZE = (WOTS_LEN1 + WOTS_LEN2) * XMSS_N | |||
print("#define XMSS_WOTS_KEYSIZE", WOTS_KEYSIZE) | |||
XMSS_H = int(param[3][1:]) | |||
print("#define XMSS_FULLHEIGHT", XMSS_H) | |||
if param[0] == 'XMSSMT': | |||
XMSS_D = int(param[4][1:]) | |||
XMSS_INDEX_LEN = floor((XMSS_H + 7) / 8) | |||
else: | |||
XMSS_INDEX_LEN = 4 # TODO fix this in the xmss code | |||
XMSS_D = 1 | |||
if int(param[3][1:]) % XMSS_D != 0: | |||
print("Make sure that d divides h!", file=sys.stderr) | |||
sys.exit(1) | |||
print("#define XMSS_TREEHEIGHT", XMSS_H // XMSS_D) | |||
print("#define XMSS_D", XMSS_D) | |||
print("#define XMSS_INDEX_LEN", XMSS_INDEX_LEN) | |||
XMSS_BYTES = XMSS_INDEX_LEN + XMSS_N + XMSS_D*WOTS_KEYSIZE + XMSS_H*XMSS_N; | |||
print("#define XMSS_BYTES", XMSS_BYTES) | |||
print("#define XMSS_PUBLICKEY_BYTES", 2*XMSS_N) | |||
print("#define XMSS_PRIVATEKEY_BYTES", 4*XMSS_N + XMSS_INDEX_LEN) | |||
print("#define XMSS_BDS_K", 2 + ((XMSS_H // XMSS_D) % 2)) # TODO figure out what we should do here | |||
print("#endif") |
@@ -3,6 +3,7 @@ | |||
#include <stdint.h> | |||
#include "../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]) { | |||
@@ -2,6 +2,8 @@ | |||
#include <string.h> | |||
#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; | |||
} | |||
@@ -3,14 +3,12 @@ | |||
#include <stdlib.h> | |||
#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; | |||
} |
@@ -2,9 +2,11 @@ | |||
#include <string.h> | |||
#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; | |||
} | |||
@@ -2,29 +2,33 @@ | |||
#include <string.h> | |||
#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; | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 |
@@ -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<<h)*n]; | |||
unsigned char tree[2*(1<<XMSS_TREEHEIGHT)*XMSS_N]; | |||
uint32_t ots_addr[8]; | |||
uint32_t ltree_addr[8]; | |||
@@ -251,32 +210,32 @@ static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, | |||
setType(node_addr, 2); | |||
// Compute all leaves | |||
for (i = 0; i < (1U << h); i++) { | |||
for (i = 0; i < (1U << XMSS_TREEHEIGHT); i++) { | |||
setLtreeADRS(ltree_addr, i); | |||
setOTSADRS(ots_addr, i); | |||
gen_leaf_wots(tree+((1<<h)*n + i*n), sk_seed, params, pub_seed, ltree_addr, ots_addr); | |||
gen_leaf_wots(tree+((1<<XMSS_TREEHEIGHT)*XMSS_N + i*XMSS_N), sk_seed, pub_seed, ltree_addr, ots_addr); | |||
} | |||
level = 0; | |||
// Compute tree: | |||
// Outer loop: For each inner layer | |||
for (i = (1<<h); i > 1; i>>=1) { | |||
for (i = (1<<XMSS_TREEHEIGHT); i > 1; i>>=1) { | |||
setTreeHeight(node_addr, level); | |||
// 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<<h)>>i)*n + ((leaf_idx >> i) ^ 1) * n, n); | |||
for (i=0; i < XMSS_TREEHEIGHT; i++) | |||
memcpy(authpath + i*XMSS_N, tree + ((1<<XMSS_TREEHEIGHT)>>i)*XMSS_N + ((leaf_idx >> i) ^ 1) * XMSS_N, XMSS_N); | |||
// copy root | |||
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; | |||
@@ -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 | |||
@@ -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 | |||