From 6a8571d880033d13ec724cf11edff75f132965f7 Mon Sep 17 00:00:00 2001 From: Joost Rijneveld Date: Mon, 16 Oct 2017 11:58:45 +0200 Subject: [PATCH] Revert to using runtime-only parameter struct Using global defines for parameters (as seems to be typical in academic crypto code) does not play nice with multithreading at all. --- Makefile | 51 +++-- README.md | 2 +- hash.c | 57 +++--- hash.h | 14 +- params_runtime.c => params.c | 112 ++++++----- params_runtime.h | 32 ---- test/test_wots.c | 25 ++- test/test_xmss.c | 25 +-- test/test_xmss_core.c | 33 ++-- test/test_xmss_core_fast.c | 53 +++--- test/test_xmssmt.c | 27 +-- test/test_xmssmt_core.c | 29 +-- test/test_xmssmt_core_fast.c | 35 ++-- wots.c | 95 +++++----- wots.h | 9 +- xmss.c | 35 ++-- xmss_commons.c | 152 +++++++-------- xmss_commons.h | 13 +- xmss_core.c | 208 ++++++++++----------- xmss_core.h | 12 +- xmss_core_fast.c | 348 ++++++++++++++++++----------------- xmss_core_fast.h | 20 +- 22 files changed, 710 insertions(+), 677 deletions(-) rename params_runtime.c => params.c (71%) delete mode 100644 params_runtime.h diff --git a/Makefile b/Makefile index 7769e30..38b886b 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,11 @@ CC = /usr/bin/gcc CFLAGS = -Wall -g -O3 -Wextra all: test/test_wots \ -test/test_xmss_core_XMSS_SHA2-256_W16_H10 \ -test/test_xmss_core_fast_XMSS_SHA2-256_W16_H10 \ +test/test_xmss_core \ +test/test_xmss_core_fast \ test/test_xmss \ -test/test_xmssmt_core_fast_XMSSMT_SHA2-256_W16_H20_D4 \ -test/test_xmssmt_core_XMSSMT_SHA2-256_W16_H20_D4 \ +test/test_xmssmt_core_fast \ +test/test_xmssmt_core \ test/test_xmssmt .PHONY: clean @@ -15,41 +15,34 @@ test/test_xmssmt params_%.h: params.h.py python3 params.h.py $(patsubst params_%.h,%,$@) > $@ -test/test_wots: params_XMSS_SHA2-256_W16_H10.h hash.c fips202.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c hash.h fips202.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 fips202.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c -o $@ -lcrypto -lm +test/test_wots: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_commons.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_commons.c test/test_wots.c -o $@ -lcrypto -lm -test/test_xmss_core_XMSS_%: params_XMSS_%.h hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmss_core.c hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h - ln -sf params_XMSS_$(patsubst test/test_xmss_core_XMSS_%,%,$@).h params.h - $(CC) $(CFLAGS) hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmss_core.c -o $@ -lcrypto -lm +test/test_xmss_core: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmss_core.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmss_core.c -o $@ -lcrypto -lm -test/test_xmss_core_fast_XMSS_%: params_XMSS_%.h hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmss_core_fast.c hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core_fast.h xmss_commons.h - ln -sf params_XMSS_$(patsubst test/test_xmss_core_fast_XMSS_%,%,$@).h params.h - $(CC) $(CFLAGS) hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmss_core_fast.c -o $@ -lcrypto -lm +test/test_xmss_core_fast: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmss_core_fast.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core_fast.h xmss_commons.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmss_core_fast.c -o $@ -lcrypto -lm -test/test_xmssmt_core_XMSSMT_%: params_XMSSMT_%.h hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmssmt_core.c hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h - ln -sf params_XMSSMT_$(patsubst test/test_xmssmt_core_XMSSMT_%,%,$@).h params.h - $(CC) $(CFLAGS) hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmssmt_core.c -o $@ -lcrypto -lm +test/test_xmssmt_core: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmssmt_core.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c test/test_xmssmt_core.c -o $@ -lcrypto -lm -test/test_xmssmt_core_fast_XMSSMT_%: params_XMSSMT_%.h hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmssmt_core_fast.c hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core_fast.h xmss_commons.h - ln -sf params_XMSSMT_$(patsubst test/test_xmssmt_core_fast_XMSSMT_%,%,$@).h params.h - $(CC) $(CFLAGS) hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmssmt_core_fast.c -o $@ -lcrypto -lm +test/test_xmssmt_core_fast: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmssmt_core_fast.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core_fast.h xmss_commons.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core_fast.c xmss_commons.c test/test_xmssmt_core_fast.c -o $@ -lcrypto -lm -test/test_xmss: params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmss.c params_runtime.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h xmss.h - ln -sf params_runtime.h params.h - $(CC) $(CFLAGS) params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmss.c -o $@ -lcrypto -lm +test/test_xmss: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmss.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h xmss.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmss.c -o $@ -lcrypto -lm -test/test_xmssmt: params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmssmt.c params_runtime.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h xmss.h - ln -sf params_runtime.h params.h - $(CC) $(CFLAGS) params_runtime.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmssmt.c -o $@ -lcrypto -lm +test/test_xmssmt: params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmssmt.c params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss_core.h xmss_commons.h xmss.h + $(CC) $(CFLAGS) params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss_core.c xmss_commons.c xmss.c test/test_xmssmt.c -o $@ -lcrypto -lm clean: -rm test/test_wots - -rm test/test_xmss_core_XMSS* - -rm test/test_xmss_core_fast_XMSS* + -rm test/test_xmss_core + -rm test/test_xmss_core_fast -rm test/test_xmss - -rm test/test_xmssmt_core_XMSS* - -rm test/test_xmssmt_core_fast_XMSS* + -rm test/test_xmssmt_core + -rm test/test_xmssmt_core_fast -rm test/test_xmssmt distclean: clean diff --git a/README.md b/README.md index ca2d9d3..54ff116 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This repository contains the reference implementation that accompanies the Internet Draft _"XMSS: Extended Hash-Based Signatures"_, [`draft-irtf-cfrg-xmss-hash-based-signatures`](https://datatracker.ietf.org/doc/draft-irtf-cfrg-xmss-hash-based-signatures/). -This reference implementation supports all parameter sets as defined in the Draft at run-time (specified by prefixing the public and private keys with a 32-bit `oid`), but also allows for compile-time parameters when directly using the internal `*_core*` functions. +This reference implementation supports all parameter sets as defined in the Draft at run-time (specified by prefixing the public and private keys with a 32-bit `oid`). Implementations that want to use compile-time parameter sets can remove the `struct xmss_params` function parameter. _While the behavior of the code in this repository is supposed to be stable, the API is not yet fully complete. In particular, the wrapper for run-time parameters does not yet support the back-end functions that make use of BDS traversal (TODO). We will also add more extensive test functionality, making it easier to compare to other XMSS implementations (TODO)._ diff --git a/hash.c b/hash.c index 6c1f3a1..3f292cf 100644 --- a/hash.c +++ b/hash.c @@ -28,7 +28,8 @@ unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]) return bytes; } -static int core_hash(unsigned char *out, const unsigned int type, +static int core_hash(const xmss_params *params, + unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, int n) { @@ -47,16 +48,16 @@ static int core_hash(unsigned char *out, const unsigned int type, buf[keylen + n + i] = in[i]; } - if (n == 32 && XMSS_FUNC == XMSS_SHA2) { + if (n == 32 && params->func == XMSS_SHA2) { SHA256(buf, inlen + keylen + n, out); } - else if (n == 32 && XMSS_FUNC == XMSS_SHAKE) { + else if (n == 32 && params->func == XMSS_SHAKE) { shake128(out, 32, buf, inlen + keylen + n); } - else if (n == 64 && XMSS_FUNC == XMSS_SHA2) { + else if (n == 64 && params->func == XMSS_SHA2) { SHA512(buf, inlen + keylen + n, out); } - else if (n == 64 && XMSS_FUNC == XMSS_SHAKE) { + else if (n == 64 && params->func == XMSS_SHAKE) { shake256(out, 64, buf, inlen + keylen + n); } else { @@ -65,66 +66,70 @@ static int core_hash(unsigned char *out, const unsigned int type, return 0; } -int prf(unsigned char *out, const unsigned char *in, +int prf(const xmss_params *params, + unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) { - return core_hash(out, 3, key, keylen, in, 32, keylen); + return core_hash(params, out, 3, key, keylen, in, 32, keylen); } -int h_msg(unsigned char *out, +int h_msg(const xmss_params *params, + unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen) { - return core_hash(out, 2, key, keylen, in, inlen, XMSS_N); + return core_hash(params, out, 2, key, keylen, in, inlen, params->n); } /** * We assume the left half is in in[0]...in[n-1] */ -int hash_h(unsigned char *out, const unsigned char *in, +int hash_h(const xmss_params *params, + unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned char buf[2*XMSS_N]; - unsigned char key[XMSS_N]; - unsigned char bitmask[2*XMSS_N]; + unsigned char buf[2*params->n]; + unsigned char key[params->n]; + unsigned char bitmask[2*params->n]; unsigned char byte_addr[32]; unsigned int i; set_key_and_mask(addr, 0); addr_to_byte(byte_addr, addr); - prf(key, byte_addr, pub_seed, XMSS_N); + prf(params, key, byte_addr, pub_seed, params->n); // Use MSB order set_key_and_mask(addr, 1); addr_to_byte(byte_addr, addr); - prf(bitmask, byte_addr, pub_seed, XMSS_N); + prf(params, bitmask, byte_addr, pub_seed, params->n); set_key_and_mask(addr, 2); addr_to_byte(byte_addr, addr); - prf(bitmask+XMSS_N, byte_addr, pub_seed, XMSS_N); - for (i = 0; i < 2*XMSS_N; i++) { + prf(params, bitmask+params->n, byte_addr, pub_seed, params->n); + for (i = 0; i < 2*params->n; i++) { buf[i] = in[i] ^ bitmask[i]; } - return core_hash(out, 1, key, XMSS_N, buf, 2*XMSS_N, XMSS_N); + return core_hash(params, out, 1, key, params->n, buf, 2*params->n, params->n); } -int hash_f(unsigned char *out, const unsigned char *in, +int hash_f(const xmss_params *params, + unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned char buf[XMSS_N]; - unsigned char key[XMSS_N]; - unsigned char bitmask[XMSS_N]; + unsigned char buf[params->n]; + unsigned char key[params->n]; + unsigned char bitmask[params->n]; unsigned char byte_addr[32]; unsigned int i; set_key_and_mask(addr, 0); addr_to_byte(byte_addr, addr); - prf(key, byte_addr, pub_seed, XMSS_N); + prf(params, key, byte_addr, pub_seed, params->n); set_key_and_mask(addr, 1); addr_to_byte(byte_addr, addr); - prf(bitmask, byte_addr, pub_seed, XMSS_N); + prf(params, bitmask, byte_addr, pub_seed, params->n); - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { buf[i] = in[i] ^ bitmask[i]; } - return core_hash(out, 0, key, XMSS_N, buf, XMSS_N, XMSS_N); + return core_hash(params, out, 0, key, params->n, buf, params->n, params->n); } diff --git a/hash.h b/hash.h index b29d976..bbd2cf2 100644 --- a/hash.h +++ b/hash.h @@ -8,21 +8,27 @@ Public domain. #ifndef HASH_H #define HASH_H +#include "params.h" + #define IS_LITTLE_ENDIAN 1 unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]); -int prf(unsigned char *out, const unsigned char *in, +int prf(const xmss_params *params, + unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen); -int h_msg(unsigned char *out, +int h_msg(const xmss_params *params, + unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen); -int hash_h(unsigned char *out, const unsigned char *in, +int hash_h(const xmss_params *params, + unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]); -int hash_f(unsigned char *out, const unsigned char *in, +int hash_f(const xmss_params *params, + unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]); #endif diff --git a/params_runtime.c b/params.c similarity index 71% rename from params_runtime.c rename to params.c index 28caf9a..1282de4 100644 --- a/params_runtime.c +++ b/params.c @@ -1,7 +1,7 @@ #include -#include "params_runtime.h" +#include "params.h" -int xmss_parse_oid(uint32_t oid) +int xmss_parse_oid(xmss_params *params, const uint32_t oid) { switch (oid) { case 0x01000001: @@ -10,7 +10,7 @@ int xmss_parse_oid(uint32_t oid) case 0x04000004: case 0x05000005: case 0x06000006: - XMSS_FUNC = XMSS_SHA2; + params->func = XMSS_SHA2; break; case 0x07000007: @@ -19,7 +19,7 @@ int xmss_parse_oid(uint32_t oid) case 0x0a00000a: case 0x0b00000b: case 0x0c00000c: - XMSS_FUNC = XMSS_SHAKE; + params->func = XMSS_SHAKE; break; default: @@ -33,7 +33,7 @@ int xmss_parse_oid(uint32_t oid) case 0x07000007: case 0x08000008: case 0x09000009: - XMSS_N = 32; + params->n = 32; break; case 0x04000004: @@ -43,7 +43,7 @@ int xmss_parse_oid(uint32_t oid) case 0x0a00000a: case 0x0b00000b: case 0x0c00000c: - XMSS_N = 64; + params->n = 64; break; default: @@ -54,53 +54,51 @@ int xmss_parse_oid(uint32_t oid) case 0x04000004: case 0x07000007: case 0x0a00000a: - XMSS_FULLHEIGHT = 10; + params->full_height = 10; break; case 0x02000002: case 0x05000005: case 0x08000008: case 0x0b00000b: - XMSS_FULLHEIGHT = 16; + params->full_height = 16; break; case 0x03000003: case 0x06000006: case 0x09000009: case 0x0c00000c: - XMSS_FULLHEIGHT = 20; + params->full_height = 20; break; default: return 1; } - XMSS_D = 1; - XMSS_TREEHEIGHT = XMSS_FULLHEIGHT / XMSS_D; - XMSS_WOTS_W = 16; - XMSS_WOTS_LOG_W = 4; - if (XMSS_N == 32) { - XMSS_WOTS_LEN1 = 64; + params->d = 1; + params->tree_height = params->full_height / params->d; + params->wots_w = 16; + params->wots_log_w = 4; + if (params->n == 32) { + params->wots_len1 = 64; } else { - XMSS_WOTS_LEN1 = 128; + params->wots_len1 = 128; } - XMSS_WOTS_LEN2 = 3; - XMSS_WOTS_LEN = XMSS_WOTS_LEN1 + XMSS_WOTS_LEN2; - XMSS_WOTS_KEYSIZE = XMSS_WOTS_LEN * XMSS_N; - XMSS_INDEX_LEN = 4; - XMSS_BYTES = (XMSS_INDEX_LEN + XMSS_N + XMSS_D*XMSS_WOTS_KEYSIZE - + XMSS_FULLHEIGHT*XMSS_N); - XMSS_PUBLICKEY_BYTES = 2*XMSS_N; - XMSS_PRIVATEKEY_BYTES = 4*XMSS_N + XMSS_INDEX_LEN; - - XMSS_OID_LEN = 4; + params->wots_len2 = 3; + params->wots_len = params->wots_len1 + params->wots_len2; + params->wots_keysize = params->wots_len * params->n; + params->index_len = 4; + params->bytes = (params->index_len + params->n + params->d*params->wots_keysize + + params->full_height *params->n); + params->publickey_bytes = 2*params->n; + params->privatekey_bytes = 4*params->n + params->index_len; // TODO figure out sensible and legal values for this based on the above - XMSS_BDS_K = 0; + params->bds_k = 0; return 0; } -int xmssmt_parse_oid(uint32_t oid) +int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) { switch (oid) { case 0x01000001: @@ -119,7 +117,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x0e00000e: case 0x0f00000f: case 0x01010101: - XMSS_FUNC = XMSS_SHA2; + params->func = XMSS_SHA2; break; case 0x02010102: @@ -138,7 +136,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x0f01010f: case 0x01020201: case 0x02020202: - XMSS_FUNC = XMSS_SHAKE; + params->func = XMSS_SHAKE; break; default: @@ -162,7 +160,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x07010107: case 0x08010108: case 0x09010109: - XMSS_N = 32; + params->n = 32; break; case 0x09000009: @@ -182,7 +180,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x0f01010f: case 0x01020201: case 0x02020202: - XMSS_N = 64; + params->n = 64; break; default: @@ -200,7 +198,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x0a01010a: case 0x0b01010b: - XMSS_FULLHEIGHT = 20; + params->full_height = 20; break; case 0x03000003: @@ -218,7 +216,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x0c01010c: case 0x0d01010d: case 0x0e01010e: - XMSS_FULLHEIGHT = 40; + params->full_height = 40; break; case 0x06000006: @@ -236,7 +234,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x0f01010f: case 0x01020201: case 0x02020202: - XMSS_FULLHEIGHT = 60; + params->full_height = 60; break; default: @@ -251,7 +249,7 @@ int xmssmt_parse_oid(uint32_t oid) case 0x04010104: case 0x0a01010a: case 0x0c01010c: - XMSS_D = 2; + params->d = 2; break; case 0x02000002: @@ -262,62 +260,60 @@ int xmssmt_parse_oid(uint32_t oid) case 0x05010105: case 0x0b01010b: case 0x0d01010d: - XMSS_D = 4; + params->d = 4; break; case 0x05000005: case 0x0d00000d: case 0x06010106: case 0x0e01010e: - XMSS_D = 8; + params->d = 8; break; case 0x06000006: case 0x0e00000e: case 0x07010107: case 0x0f01010f: - XMSS_D = 3; + params->d = 3; break; case 0x07000007: case 0x0f00000f: case 0x08010108: case 0x01020201: - XMSS_D = 6; + params->d = 6; break; case 0x08000008: case 0x01010101: case 0x09010109: case 0x02020202: - XMSS_D = 12; + params->d = 12; break; default: return 1; } - XMSS_TREEHEIGHT = XMSS_FULLHEIGHT / XMSS_D; - XMSS_WOTS_W = 16; - XMSS_WOTS_LOG_W = 4; - if (XMSS_N == 32) { - XMSS_WOTS_LEN1 = 64; + params->tree_height = params->full_height / params->d; + params->wots_w = 16; + params->wots_log_w = 4; + if (params->n == 32) { + params->wots_len1 = 64; } else { - XMSS_WOTS_LEN1 = 128; + params->wots_len1 = 128; } - XMSS_WOTS_LEN2 = 3; - XMSS_WOTS_LEN = XMSS_WOTS_LEN1 + XMSS_WOTS_LEN2; - XMSS_WOTS_KEYSIZE = XMSS_WOTS_LEN * XMSS_N; - XMSS_INDEX_LEN = 4; - XMSS_BYTES = (XMSS_INDEX_LEN + XMSS_N + XMSS_D*XMSS_WOTS_KEYSIZE - + XMSS_FULLHEIGHT*XMSS_N); - XMSS_PUBLICKEY_BYTES = 2*XMSS_N; - XMSS_PRIVATEKEY_BYTES = 4*XMSS_N + XMSS_INDEX_LEN; - - XMSS_OID_LEN = 4; + params->wots_len2 = 3; + params->wots_len = params->wots_len1 + params->wots_len2; + params->wots_keysize = params->wots_len * params->n; + params->index_len = 4; + params->bytes = (params->index_len + params->n + params->d*params->wots_keysize + + params->full_height *params->n); + params->publickey_bytes = 2*params->n; + params->privatekey_bytes = 4*params->n + params->index_len; // TODO figure out sensible and legal values for this based on the above - XMSS_BDS_K = 0; + params->bds_k = 0; return 0; } diff --git a/params_runtime.h b/params_runtime.h deleted file mode 100644 index 5963643..0000000 --- a/params_runtime.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PARAMS_H -#define PARAMS_H - -#include - -// These are simply internal identifiers for the supported hash functions -#define XMSS_SHA2 0 -#define XMSS_SHAKE 1 - -// These parameters can be used after calling xmss[mt]_parse_oid(oid). -unsigned int XMSS_FUNC; -unsigned int XMSS_N; -unsigned int XMSS_WOTS_W; -unsigned int XMSS_WOTS_LOG_W; -unsigned int XMSS_WOTS_LEN1; -unsigned int XMSS_WOTS_LEN2; -unsigned int XMSS_WOTS_LEN; -unsigned int XMSS_WOTS_KEYSIZE; -unsigned int XMSS_FULLHEIGHT; -unsigned int XMSS_TREEHEIGHT; -unsigned int XMSS_D; -unsigned int XMSS_INDEX_LEN; -unsigned int XMSS_BYTES; -unsigned int XMSS_PUBLICKEY_BYTES; -unsigned int XMSS_PRIVATEKEY_BYTES; -unsigned int XMSS_OID_LEN; -unsigned int XMSS_BDS_K; - -int xmss_parse_oid(uint32_t oid); -int xmssmt_parse_oid(uint32_t oid); - -#endif \ No newline at end of file diff --git a/test/test_wots.c b/test/test_wots.c index a361cd2..3c3a29a 100644 --- a/test/test_wots.c +++ b/test/test_wots.c @@ -14,27 +14,32 @@ static void hexdump(unsigned char *a, size_t len) int main() { - unsigned char seed[XMSS_N]; - unsigned char pub_seed[XMSS_N]; + xmss_params params; + // TODO test more different OIDs + uint32_t oid = 0x01000001; + xmssmt_parse_oid(¶ms, oid); - int sig_len = XMSS_WOTS_LEN*XMSS_N; + unsigned char seed[params.n]; + unsigned char pub_seed[params.n]; + + int sig_len = params.wots_len*params.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[XMSS_N]; + unsigned char msg[params.n]; int i; - randombytes(seed, XMSS_N); - randombytes(pub_seed, XMSS_N); - randombytes(msg, XMSS_N); + randombytes(seed, params.n); + randombytes(pub_seed, params.n); + randombytes(msg, params.n); //randombytes(addr, 16); - wots_pkgen(pk1, seed, pub_seed, addr); - wots_sign(sig, msg, seed, pub_seed, addr); - wots_pk_from_sig(pk2, sig, msg, pub_seed, addr); + wots_pkgen(¶ms, pk1, seed, pub_seed, addr); + wots_sign(¶ms, sig, msg, seed, pub_seed, addr); + wots_pk_from_sig(¶ms, 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 780563c..d2911ad 100644 --- a/test/test_xmss.c +++ b/test/test_xmss.c @@ -15,26 +15,27 @@ unsigned long long mlen; int main() { + xmss_params params; // TODO test more different OIDs uint32_t oid = 0x01000001; - xmss_parse_oid(oid); // Parse it to make sure the sizes are set + xmss_parse_oid(¶ms, oid); int r; unsigned long long i, j; unsigned long errors = 0; - unsigned char sk[XMSS_OID_LEN + XMSS_PRIVATEKEY_BYTES]; - unsigned char pk[XMSS_OID_LEN + XMSS_PUBLICKEY_BYTES]; + unsigned char sk[XMSS_OID_LEN + params.privatekey_bytes]; + unsigned char pk[XMSS_OID_LEN + params.publickey_bytes]; - unsigned char mo[MLEN+XMSS_BYTES]; - unsigned char sm[MLEN+XMSS_BYTES]; + unsigned char mo[MLEN+params.bytes]; + unsigned char sm[MLEN+params.bytes]; printf("keypair\n"); xmss_keypair(pk, sk, oid); // check pub_seed in SK - for (i = 0; i < XMSS_N; i++) { - if (pk[XMSS_OID_LEN+XMSS_N+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); - if (pk[XMSS_OID_LEN+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i); + for (i = 0; i < params.n; i++) { + if (pk[XMSS_OID_LEN+params.n+i] != sk[XMSS_OID_LEN+params.index_len+2*params.n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[XMSS_OID_LEN+i] != sk[XMSS_OID_LEN+params.index_len+3*params.n+i]) printf("pk.root != sk.root %llu",i); } // check index @@ -54,7 +55,7 @@ int main() } printf("\n"); - r = memcmp(mi, sm+XMSS_BYTES,MLEN); + r = memcmp(mi, sm+params.bytes,MLEN); printf("%d\n", r); /* Test valid signature */ @@ -67,7 +68,7 @@ int main() printf("%llu\n", MLEN-mlen); /* Test with modified message */ - sm[XMSS_BYTES+10] ^= 1; + sm[params.bytes+10] ^= 1; r = xmss_sign_open(mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; @@ -77,7 +78,7 @@ int main() /* Test with modified signature */ /* Modified index */ - sm[XMSS_BYTES+10] ^= 1; + sm[params.bytes+10] ^= 1; sm[2] ^= 1; r = xmss_sign_open(mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); @@ -108,7 +109,7 @@ int main() /* Modified AUTH */ sm[240] ^= 1; - sm[XMSS_BYTES - 10] ^= 1; + sm[params.bytes - 10] ^= 1; r = xmss_sign_open(mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; diff --git a/test/test_xmss_core.c b/test/test_xmss_core.c index 5e2cdc7..65cbd06 100644 --- a/test/test_xmss_core.c +++ b/test/test_xmss_core.c @@ -14,23 +14,28 @@ unsigned long long mlen; int main() { + xmss_params params; + // TODO test more different OIDs + uint32_t oid = 0x01000001; + xmss_parse_oid(¶ms, oid); + int r; unsigned long long i, j; unsigned long errors = 0; - unsigned char sk[4*XMSS_N+4]; - unsigned char pk[2*XMSS_N]; + unsigned char sk[4*params.n+4]; + unsigned char pk[2*params.n]; - unsigned long long signature_length = 4+XMSS_N+XMSS_WOTS_KEYSIZE+XMSS_TREEHEIGHT*XMSS_N; + unsigned long long signature_length = 4+params.n+params.wots_keysize+params.tree_height*params.n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; printf("keypair\n"); - xmss_core_keypair(pk, sk); + xmss_core_keypair(¶ms, pk, sk); // check pub_seed in SK - 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); + for (i = 0; i < params.n; i++) { + if (pk[params.n+i] != sk[4+2*params.n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[4+3*params.n+i]) printf("pk.root != sk.root %llu",i); } // check index @@ -41,7 +46,7 @@ int main() randombytes(mi, MLEN); printf("sign\n"); - xmss_core_sign(sk, sm, &smlen, mi, MLEN); + xmss_core_sign(¶ms, 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); @@ -55,7 +60,7 @@ int main() /* Test valid signature */ printf("verify\n"); - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r); if (r != 0) errors++; r = memcmp(mi,mo,MLEN); @@ -64,7 +69,7 @@ int main() /* Test with modified message */ sm[signature_length+10] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -75,7 +80,7 @@ int main() /* Modified index */ sm[signature_length+10] ^= 1; sm[2] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -85,7 +90,7 @@ int main() /* Modified R */ sm[2] ^= 1; sm[5] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -95,7 +100,7 @@ int main() /* Modified OTS sig */ sm[5] ^= 1; sm[240] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -105,7 +110,7 @@ int main() /* Modified AUTH */ sm[240] ^= 1; sm[signature_length - 10] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); diff --git a/test/test_xmss_core_fast.c b/test/test_xmss_core_fast.c index 2d7ea1d..150a517 100644 --- a/test/test_xmss_core_fast.c +++ b/test/test_xmss_core_fast.c @@ -20,31 +20,36 @@ unsigned long long cpucycles(void) int main() { + xmss_params params; + // TODO test more different OIDs + uint32_t oid = 0x01000001; + xmss_parse_oid(¶ms, oid); + int r; unsigned long long i; - unsigned int k = XMSS_BDS_K; + unsigned int k = params.bds_k; unsigned long errors = 0; - unsigned char sk[4*XMSS_N+4]; - unsigned char pk[2*XMSS_N]; + unsigned char sk[4*params.n+4]; + unsigned char pk[2*params.n]; // TODO should we hide this into xmss_fast.c and just allocate a large enough chunk of memory here? - unsigned char stack[(XMSS_TREEHEIGHT+1)*XMSS_N]; + unsigned char stack[(params.tree_height+1)*params.n]; unsigned int stackoffset = 0; - 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]; + unsigned char stacklevels[params.tree_height+1]; + unsigned char auth[(params.tree_height)*params.n]; + unsigned char keep[(params.tree_height >> 1)*params.n]; + treehash_inst treehash[params.tree_height-k]; + unsigned char th_nodes[(params.tree_height-k)*params.n]; + unsigned char retain[((1 << k) - k - 1)*params.n]; bds_state s; bds_state *state = &s; - for (i = 0; i < XMSS_TREEHEIGHT-k; i++) - treehash[i].node = &th_nodes[XMSS_N*i]; + for (i = 0; i < params.tree_height-k; i++) + treehash[i].node = &th_nodes[params.n*i]; xmss_set_bds_state(state, stack, stackoffset, stacklevels, auth, keep, treehash, retain, 0); - unsigned long long signature_length = 4+XMSS_N+XMSS_WOTS_KEYSIZE+XMSS_TREEHEIGHT*XMSS_N; + unsigned long long signature_length = 4+params.n+params.wots_keysize+params.tree_height*params.n; unsigned char mi[MLEN]; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; @@ -55,15 +60,15 @@ int main() printf("keypair\n"); t1 = cpucycles(); - xmss_core_keypair(pk, sk, state); + xmss_core_keypair(¶ms, pk, sk, state); t2 = cpucycles(); printf("cycles = %llu\n", (t2-t1)); double sec = (t2-t1)/3500000; printf("ms = %f\n", sec); // check pub_seed in SK - 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); + for (i = 0; i < params.n; i++) { + if (pk[params.n+i] != sk[4+2*params.n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[4+3*params.n+i]) printf("pk.root != sk.root %llu",i); } // check index @@ -72,7 +77,7 @@ int main() for (i = 0; i < SIGNATURES; i++) { printf("sign\n"); - xmss_core_sign(sk, state, sm, &smlen, mi, MLEN); + xmss_core_sign(¶ms, 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); @@ -81,7 +86,7 @@ int main() /* Test valid signature */ printf("verify\n"); - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r); if (r != 0) errors++; r = memcmp(mi,mo,MLEN); @@ -90,7 +95,7 @@ int main() /* Test with modified message */ sm[signature_length+10] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -101,7 +106,7 @@ int main() /* Modified index */ sm[signature_length+10] ^= 1; sm[2] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -111,7 +116,7 @@ int main() /* Modified R */ sm[2] ^= 1; sm[5] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -121,7 +126,7 @@ int main() /* Modified OTS sig */ sm[5] ^= 1; sm[240] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); @@ -131,7 +136,7 @@ int main() /* Modified AUTH */ sm[240] ^= 1; sm[signature_length - 10] ^= 1; - r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); if (r == 0) errors++; r = memcmp(mi,mo,MLEN); diff --git a/test/test_xmssmt.c b/test/test_xmssmt.c index 0599c5b..8218a70 100644 --- a/test/test_xmssmt.c +++ b/test/test_xmssmt.c @@ -15,33 +15,34 @@ unsigned long long mlen; int main() { + xmss_params params; // TODO test more different OIDs uint32_t oid = 0x01000001; - xmssmt_parse_oid(oid); // Parse it to make sure the sizes are set + xmssmt_parse_oid(¶ms, oid); int r; unsigned long long i,j; - unsigned char sk[XMSS_OID_LEN + XMSS_PRIVATEKEY_BYTES]; - unsigned char pk[XMSS_OID_LEN + XMSS_PUBLICKEY_BYTES]; + unsigned char sk[XMSS_OID_LEN + params.privatekey_bytes]; + unsigned char pk[XMSS_OID_LEN + params.publickey_bytes]; - unsigned char mo[MLEN+XMSS_BYTES]; - unsigned char sm[MLEN+XMSS_BYTES]; + unsigned char mo[MLEN+params.bytes]; + unsigned char sm[MLEN+params.bytes]; printf("keypair\n"); xmssmt_keypair(pk, sk, oid); // check pub_seed in SK - for (i = 0; i < XMSS_N; i++) { - if (pk[XMSS_OID_LEN+XMSS_N+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+2*XMSS_N+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); - if (pk[XMSS_OID_LEN+i] != sk[XMSS_OID_LEN+XMSS_INDEX_LEN+3*XMSS_N+i]) printf("pk.root != sk.root %llu",i); + for (i = 0; i < params.n; i++) { + if (pk[XMSS_OID_LEN+params.n+i] != sk[XMSS_OID_LEN+params.index_len+2*params.n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[XMSS_OID_LEN+i] != sk[XMSS_OID_LEN+params.index_len+3*params.n+i]) printf("pk.root != sk.root %llu",i); } printf("pk checked\n"); // check index unsigned long long idx = 0; - for (i = 0; i < XMSS_INDEX_LEN; i++) { - idx |= ((unsigned long long)sk[i + XMSS_OID_LEN]) << 8*(XMSS_INDEX_LEN - 1 - i); + for (i = 0; i < params.index_len; i++) { + idx |= ((unsigned long long)sk[i + XMSS_OID_LEN]) << 8*(params.index_len - 1 - i); } if (idx) printf("\nidx != 0: %llu\n",idx); @@ -52,11 +53,11 @@ int main() printf("sign\n"); xmssmt_sign(sk, sm, &smlen, mi, MLEN); idx = 0; - for (j = 0; j < XMSS_INDEX_LEN; j++) { - idx += ((unsigned long long)sm[j]) << 8*(XMSS_INDEX_LEN - 1 - j); + for (j = 0; j < params.index_len; j++) { + idx += ((unsigned long long)sm[j]) << 8*(params.index_len - 1 - j); } printf("\nidx = %llu\n",idx); - r = memcmp(mi, sm+XMSS_BYTES,MLEN); + r = memcmp(mi, sm+params.bytes,MLEN); printf("%d\n", r); for (j = 0; j < smlen; j++) { diff --git a/test/test_xmssmt_core.c b/test/test_xmssmt_core.c index 642b90a..000906d 100644 --- a/test/test_xmssmt_core.c +++ b/test/test_xmssmt_core.c @@ -14,26 +14,31 @@ unsigned long long mlen; int main() { + xmss_params params; + // TODO test more different OIDs + uint32_t oid = 0x01000001; + xmssmt_parse_oid(¶ms, oid); + int r; unsigned long long i,j; - unsigned char sk[(XMSS_INDEX_LEN+4*XMSS_N)]; - unsigned char pk[2*XMSS_N]; + unsigned char sk[(params.index_len+4*params.n)]; + unsigned char pk[2*params.n]; - unsigned long long signature_length = XMSS_INDEX_LEN + XMSS_N + (XMSS_D*XMSS_WOTS_KEYSIZE) + XMSS_FULLHEIGHT*XMSS_N; + unsigned long long signature_length = params.index_len + params.n + (params.d*params.wots_keysize) + params.full_height*params.n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; printf("keypair\n"); - xmssmt_core_keypair(pk, sk); + xmssmt_core_keypair(¶ms, pk, sk); // check pub_seed in SK - 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); + for (i = 0; i < params.n; i++) { + if (pk[params.n+i] != sk[params.index_len+2*params.n+i]) printf("pk.pub_seed != sk.pub_seed %llu",i); + if (pk[i] != sk[params.index_len+3*params.n+i]) printf("pk.root != sk.root %llu",i); } printf("pk checked\n"); - unsigned int idx_len = XMSS_INDEX_LEN; + unsigned int idx_len = params.index_len; // check index unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { @@ -46,7 +51,7 @@ int main() randombytes(mi, MLEN); printf("sign\n"); - xmssmt_core_sign(sk, sm, &smlen, mi, MLEN); + xmssmt_core_sign(¶ms, 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,7 +67,7 @@ int main() /* Test valid signature */ printf("verify\n"); - r = xmssmt_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmssmt_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r); r = memcmp(mi,mo,MLEN); printf("%d\n", r); @@ -70,7 +75,7 @@ int main() /* Test with modified message */ sm[52] ^= 1; - r = xmssmt_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmssmt_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); @@ -80,7 +85,7 @@ int main() sm[260] ^= 1; sm[52] ^= 1; sm[2] ^= 1; - r = xmssmt_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmssmt_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); diff --git a/test/test_xmssmt_core_fast.c b/test/test_xmssmt_core_fast.c index 4579d05..653db48 100644 --- a/test/test_xmssmt_core_fast.c +++ b/test/test_xmssmt_core_fast.c @@ -23,12 +23,17 @@ unsigned long long cpucycles(void) int main() { + xmss_params params; + // TODO test more different OIDs + uint32_t oid = 0x01000001; + xmssmt_parse_oid(¶ms, oid); + int r; unsigned long long i,j; - unsigned int n = XMSS_N; - unsigned int h = XMSS_FULLHEIGHT; - unsigned int d = XMSS_D; - unsigned int k = XMSS_BDS_K; + unsigned int n = params.n; + unsigned int h = params.full_height; + unsigned int d = params.d; + unsigned int k = params.bds_k; unsigned int tree_h = h / d; @@ -40,7 +45,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 * XMSS_WOTS_KEYSIZE]; + unsigned char wots_sigs[d * params.wots_keysize]; // first d are 'regular' states, second d are 'next'; top tree has no 'next' bds_state states[2*d-1]; @@ -57,25 +62,25 @@ int main() ); } - unsigned char sk[(XMSS_INDEX_LEN+4*n)]; + unsigned char sk[(params.index_len+4*n)]; unsigned char pk[2*n]; - unsigned long long signature_length = XMSS_INDEX_LEN + n + (d*XMSS_WOTS_KEYSIZE) + h*n; + unsigned long long signature_length = params.index_len + n + (d*params.wots_keysize) + h*n; unsigned char mo[MLEN+signature_length]; unsigned char sm[MLEN+signature_length]; randombytes(mi, MLEN); printf("keypair\n"); - xmssmt_core_keypair(pk, sk, states, wots_sigs); + xmssmt_core_keypair(¶ms, pk, sk, states, wots_sigs); // check pub_seed in SK for (i = 0; i < n; 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); + 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); } printf("pk checked\n"); - unsigned int idx_len = XMSS_INDEX_LEN; + unsigned int idx_len = params.index_len; // check index unsigned long long idx = 0; for (i = 0; i < idx_len; i++) { @@ -87,7 +92,7 @@ int main() for (i = 0; i < SIGNATURES; i++) { printf("sign\n"); t1 = cpucycles(); - xmssmt_core_sign(sk, states, wots_sigs, sm, &smlen, mi, MLEN); + xmssmt_core_sign(¶ms, sk, states, wots_sigs, sm, &smlen, mi, MLEN); t2 = cpucycles(); printf("signing cycles = %llu\n", (t2-t1)); @@ -102,7 +107,7 @@ int main() /* Test valid signature */ printf("verify\n"); t1 = cpucycles(); - r = xmssmt_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmssmt_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); t2 = cpucycles(); printf("verification cycles = %llu\n", (t2-t1)); printf("%d\n", r); @@ -112,7 +117,7 @@ int main() /* Test with modified message */ sm[52] ^= 1; - r = xmssmt_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmssmt_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); @@ -122,7 +127,7 @@ int main() sm[260] ^= 1; sm[52] ^= 1; sm[2] ^= 1; - r = xmssmt_core_sign_open(mo, &mlen, sm, smlen, pk); + r = xmssmt_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); printf("%d\n", r+1); r = memcmp(mi,mo,MLEN); printf("%d\n", (r!=0) - 1); diff --git a/wots.c b/wots.c index e0c7acb..ecf02f3 100644 --- a/wots.c +++ b/wots.c @@ -17,14 +17,15 @@ Public domain. * 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) +static void expand_seed(const xmss_params *params, + unsigned char *outseeds, const unsigned char *inseed) { uint32_t i; unsigned char ctr[32]; - for (i = 0; i < XMSS_WOTS_LEN; i++) { + for (i = 0; i < params->wots_len; i++) { to_byte(ctr, i, 32); - prf(outseeds + i*XMSS_N, ctr, inseed, XMSS_N); + prf(params, outseeds + i*params->n, ctr, inseed, params->n); } } @@ -35,26 +36,28 @@ static void expand_seed(unsigned char *outseeds, const unsigned char *inseed) * 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, +static void gen_chain(const xmss_params *params, + 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; - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { out[i] = in[i]; } - for (i = start; i < (start+steps) && i < XMSS_WOTS_W; i++) { + for (i = start; i < (start+steps) && i < params->wots_w; i++) { set_hash_addr(addr, i); - hash_f(out, out, pub_seed, addr); + hash_f(params, out, out, pub_seed, addr); } } /** * base_w algorithm as described in draft. */ -static void base_w(int *output, const int out_len, const unsigned char *input) +static void base_w(const xmss_params *params, + int *output, const int out_len, const unsigned char *input) { int in = 0; int out = 0; @@ -68,87 +71,89 @@ static void base_w(int *output, const int out_len, const unsigned char *input) in++; bits += 8; } - bits -= XMSS_WOTS_LOG_W; - output[out] = (total >> bits) & (XMSS_WOTS_W - 1); + bits -= params->wots_log_w; + output[out] = (total >> bits) & (params->wots_w - 1); out++; } } -void wots_pkgen(unsigned char *pk, const unsigned char *sk, +void wots_pkgen(const xmss_params *params, + unsigned char *pk, const unsigned char *sk, const unsigned char *pub_seed, uint32_t addr[8]) { uint32_t i; - expand_seed(pk, sk); - for (i = 0; i < XMSS_WOTS_LEN; i++) { + expand_seed(params, pk, sk); + for (i = 0; i < params->wots_len; i++) { set_chain_addr(addr, i); - gen_chain(pk + i*XMSS_N, pk + i*XMSS_N, - 0, XMSS_WOTS_W-1, pub_seed, addr); + gen_chain(params, pk + i*params->n, pk + i*params->n, + 0, params->wots_w-1, pub_seed, addr); } } -void wots_sign(unsigned char *sig, const unsigned char *msg, +void wots_sign(const xmss_params *params, + unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const unsigned char *pub_seed, uint32_t addr[8]) { - int basew[XMSS_WOTS_LEN]; + int basew[params->wots_len]; int csum = 0; - unsigned char csum_bytes[((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) + 7) / 8]; - int csum_basew[XMSS_WOTS_LEN2]; + unsigned char csum_bytes[((params->wots_len2 * params->wots_log_w) + 7) / 8]; + int csum_basew[params->wots_len2]; uint32_t i; - base_w(basew, XMSS_WOTS_LEN1, msg); + base_w(params, basew, params->wots_len1, msg); - for (i = 0; i < XMSS_WOTS_LEN1; i++) { - csum += XMSS_WOTS_W - 1 - basew[i]; + for (i = 0; i < params->wots_len1; i++) { + csum += params->wots_w - 1 - basew[i]; } - csum = csum << (8 - ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) % 8)); + csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8)); - to_byte(csum_bytes, csum, ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) + 7) / 8); - base_w(csum_basew, XMSS_WOTS_LEN2, csum_bytes); + to_byte(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8); + base_w(params, csum_basew, params->wots_len2, csum_bytes); - for (i = 0; i < XMSS_WOTS_LEN2; i++) { - basew[XMSS_WOTS_LEN1 + i] = csum_basew[i]; + for (i = 0; i < params->wots_len2; i++) { + basew[params->wots_len1 + i] = csum_basew[i]; } - expand_seed(sig, sk); + expand_seed(params, sig, sk); - for (i = 0; i < XMSS_WOTS_LEN; i++) { + for (i = 0; i < params->wots_len; i++) { set_chain_addr(addr, i); - gen_chain(sig + i*XMSS_N, sig + i*XMSS_N, + gen_chain(params, sig + i*params->n, sig + i*params->n, 0, basew[i], pub_seed, addr); } } -void wots_pk_from_sig(unsigned char *pk, +void wots_pk_from_sig(const xmss_params *params, unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const unsigned char *pub_seed, uint32_t addr[8]) { - int basew[XMSS_WOTS_LEN]; + int basew[params->wots_len]; int csum = 0; - unsigned char csum_bytes[((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) + 7) / 8]; - int csum_basew[XMSS_WOTS_LEN2]; + unsigned char csum_bytes[((params->wots_len2 * params->wots_log_w) + 7) / 8]; + int csum_basew[params->wots_len2]; uint32_t i = 0; - base_w(basew, XMSS_WOTS_LEN1, msg); + base_w(params, basew, params->wots_len1, msg); - for (i=0; i < XMSS_WOTS_LEN1; i++) { - csum += XMSS_WOTS_W - 1 - basew[i]; + for (i=0; i < params->wots_len1; i++) { + csum += params->wots_w - 1 - basew[i]; } - csum = csum << (8 - ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) % 8)); + csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8)); - to_byte(csum_bytes, csum, ((XMSS_WOTS_LEN2 * XMSS_WOTS_LOG_W) + 7) / 8); - base_w(csum_basew, XMSS_WOTS_LEN2, csum_bytes); + to_byte(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8); + base_w(params, csum_basew, params->wots_len2, csum_bytes); - for (i = 0; i < XMSS_WOTS_LEN2; i++) { - basew[XMSS_WOTS_LEN1 + i] = csum_basew[i]; + for (i = 0; i < params->wots_len2; i++) { + basew[params->wots_len1 + i] = csum_basew[i]; } - for (i=0; i < XMSS_WOTS_LEN; i++) { + for (i=0; i < params->wots_len; i++) { set_chain_addr(addr, i); - gen_chain(pk + i*XMSS_N, sig + i*XMSS_N, - basew[i], XMSS_WOTS_W-1-basew[i], pub_seed, addr); + gen_chain(params, pk + i*params->n, sig + i*params->n, + basew[i], params->wots_w-1-basew[i], pub_seed, addr); } } diff --git a/wots.h b/wots.h index 02dfbd7..0aeb98f 100644 --- a/wots.h +++ b/wots.h @@ -9,6 +9,7 @@ Public domain. #define WOTS_H #include +#include "params.h" /** * 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. @@ -16,20 +17,22 @@ Public domain. * * Places the computed public key at address pk. */ -void wots_pkgen(unsigned char *pk, const unsigned char *sk, +void wots_pkgen(const xmss_params *params, + 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, +void wots_sign(const xmss_params *params, + 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_pk_from_sig(unsigned char *pk, +void wots_pk_from_sig(const xmss_params *params, unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const unsigned char *pub_seed, uint32_t addr[8]); diff --git a/xmss.c b/xmss.c index 613e17d..7b9253a 100644 --- a/xmss.c +++ b/xmss.c @@ -1,6 +1,6 @@ #include -#include "params_runtime.h" +#include "params.h" #include "xmss_core.h" /* This file provides wrapper functions that take keys that include OIDs to @@ -9,94 +9,101 @@ it falls back to the regular XMSS core functions. */ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) { + xmss_params params; unsigned int i; - if (xmss_parse_oid(oid)) { + if (xmss_parse_oid(¶ms, oid)) { return 1; } for (i = 0; i < XMSS_OID_LEN; i++) { pk[i] = (oid >> (8 * i)) & 0xFF; /* For an implementation that uses runtime parameters, it is crucial - that the OID is part of the secret key as well. */ + that the OID is part of the secret key as well; + i.e. not just for interoperability, but also for internal use. */ sk[i] = (oid >> (8 * i)) & 0xFF; } - return xmss_core_keypair(pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); + return xmss_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); } int xmss_sign(unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) { + xmss_params params; uint32_t oid = 0; unsigned int i; for (i = 0; i < XMSS_OID_LEN; i++) { oid |= sk[i] << (i * 8); } - if (xmss_parse_oid(oid)) { + if (xmss_parse_oid(¶ms, oid)) { return 1; } - return xmss_core_sign(sk + XMSS_OID_LEN, sm, smlen, m, mlen); + return xmss_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); } int xmss_sign_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { + xmss_params params; uint32_t oid = 0; unsigned int i; for (i = 0; i < XMSS_OID_LEN; i++) { oid |= pk[i] << (i * 8); } - if (xmss_parse_oid(oid)) { + if (xmss_parse_oid(¶ms, oid)) { return 1; } - return xmss_core_sign_open(m, mlen, sm, smlen, pk + XMSS_OID_LEN); + return xmss_core_sign_open(¶ms, m, mlen, sm, smlen, pk + XMSS_OID_LEN); } int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) { + xmss_params params; unsigned int i; - if (xmssmt_parse_oid(oid)) { + if (xmssmt_parse_oid(¶ms, oid)) { return 1; } for (i = 0; i < XMSS_OID_LEN; i++) { pk[i] = (oid >> (8 * i)) & 0xFF; sk[i] = (oid >> (8 * i)) & 0xFF; } - return xmssmt_core_keypair(pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); + return xmssmt_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); } int xmssmt_sign(unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) { + xmss_params params; uint32_t oid = 0; unsigned int i; for (i = 0; i < XMSS_OID_LEN; i++) { oid |= sk[i] << (i * 8); } - if (xmssmt_parse_oid(oid)) { + if (xmssmt_parse_oid(¶ms, oid)) { return 1; } - return xmssmt_core_sign(sk + XMSS_OID_LEN, sm, smlen, m, mlen); + return xmssmt_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); } int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { + xmss_params params; uint32_t oid = 0; unsigned int i; for (i = 0; i < XMSS_OID_LEN; i++) { oid |= pk[i] << (i * 8); } - if (xmssmt_parse_oid(oid)) { + if (xmssmt_parse_oid(¶ms, oid)) { return 1; } - return xmssmt_core_sign_open(m, mlen, sm, smlen, pk + XMSS_OID_LEN); + return xmssmt_core_sign_open(¶ms, m, mlen, sm, smlen, pk + XMSS_OID_LEN); } diff --git a/xmss_commons.c b/xmss_commons.c index 3bcf2ca..521a979 100644 --- a/xmss_commons.c +++ b/xmss_commons.c @@ -28,26 +28,26 @@ void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes) /** * 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. */ -void gen_leaf_wots(unsigned char *leaf, +void gen_leaf_wots(const xmss_params *params, 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[XMSS_N]; - unsigned char pk[XMSS_WOTS_KEYSIZE]; + unsigned char seed[params->n]; + unsigned char pk[params->wots_keysize]; - get_seed(seed, sk_seed, ots_addr); - wots_pkgen(pk, seed, pub_seed, ots_addr); + get_seed(params, seed, sk_seed, ots_addr); + wots_pkgen(params, pk, seed, pub_seed, ots_addr); - l_tree(leaf, pk, pub_seed, ltree_addr); + l_tree(params, leaf, pk, pub_seed, ltree_addr); } /** * Used for pseudorandom keygeneration, * generates the seed for the WOTS keypair at address addr * - * takes XMSS_N byte sk_seed and returns XMSS_N byte seed using 32 byte address addr. + * takes params->n byte sk_seed and returns params->n byte seed using 32 byte address addr. */ -void get_seed(unsigned char *seed, +void get_seed(const xmss_params *params, unsigned char *seed, const unsigned char *sk_seed, uint32_t addr[8]) { unsigned char bytes[32]; @@ -58,16 +58,16 @@ void get_seed(unsigned char *seed, set_key_and_mask(addr, 0); // Generate pseudorandom value addr_to_byte(bytes, addr); - prf(seed, bytes, sk_seed, XMSS_N); + prf(params, seed, bytes, sk_seed, params->n); } /** * Computes a leaf from a WOTS public key using an L-tree. */ -void l_tree(unsigned char *leaf, unsigned char *wots_pk, +void l_tree(const xmss_params *params, unsigned char *leaf, unsigned char *wots_pk, const unsigned char *pub_seed, uint32_t addr[8]) { - unsigned int l = XMSS_WOTS_LEN; + unsigned int l = params->wots_len; uint32_t i = 0; uint32_t height = 0; uint32_t bound; @@ -78,10 +78,10 @@ void l_tree(unsigned char *leaf, unsigned char *wots_pk, bound = l >> 1; for (i = 0; i < bound; i++) { set_tree_index(addr, i); - hash_h(wots_pk + i*XMSS_N, wots_pk + i*2*XMSS_N, pub_seed, addr); + hash_h(params, wots_pk + i*params->n, wots_pk + i*2*params->n, pub_seed, addr); } if (l & 1) { - memcpy(wots_pk + (l >> 1)*XMSS_N, wots_pk + (l - 1)*XMSS_N, XMSS_N); + memcpy(wots_pk + (l >> 1)*params->n, wots_pk + (l - 1)*params->n, params->n); l = (l >> 1) + 1; } else { @@ -90,77 +90,78 @@ void l_tree(unsigned char *leaf, unsigned char *wots_pk, height++; set_tree_height(addr, height); } - memcpy(leaf, wots_pk, XMSS_N); + memcpy(leaf, wots_pk, params->n); } /** * Computes a root node given a leaf and an authapth */ -static void validate_authpath(unsigned char *root, +static void validate_authpath(const xmss_params *params, unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const unsigned char *pub_seed, uint32_t addr[8]) { uint32_t i, j; - unsigned char buffer[2*XMSS_N]; + unsigned char buffer[2*params->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 < XMSS_N; j++) { - buffer[XMSS_N + j] = leaf[j]; + for (j = 0; j < params->n; j++) { + buffer[params->n + j] = leaf[j]; buffer[j] = authpath[j]; } } else { - for (j = 0; j < XMSS_N; j++) { + for (j = 0; j < params->n; j++) { buffer[j] = leaf[j]; - buffer[XMSS_N + j] = authpath[j]; + buffer[params->n + j] = authpath[j]; } } - authpath += XMSS_N; + authpath += params->n; - for (i = 0; i < XMSS_TREEHEIGHT-1; i++) { + for (i = 0; i < params->tree_height-1; i++) { set_tree_height(addr, i); leafidx >>= 1; set_tree_index(addr, leafidx); if (leafidx & 1) { - hash_h(buffer + XMSS_N, buffer, pub_seed, addr); - for (j = 0; j < XMSS_N; j++) { + hash_h(params, buffer + params->n, buffer, pub_seed, addr); + for (j = 0; j < params->n; j++) { buffer[j] = authpath[j]; } } else { - hash_h(buffer, buffer, pub_seed, addr); - for (j = 0; j < XMSS_N; j++) { - buffer[j + XMSS_N] = authpath[j]; + hash_h(params, buffer, buffer, pub_seed, addr); + for (j = 0; j < params->n; j++) { + buffer[j + params->n] = authpath[j]; } } - authpath += XMSS_N; + authpath += params->n; } - set_tree_height(addr, XMSS_TREEHEIGHT - 1); + set_tree_height(addr, params->tree_height - 1); leafidx >>= 1; set_tree_index(addr, leafidx); - hash_h(root, buffer, pub_seed, addr); + hash_h(params, root, buffer, pub_seed, addr); } /** * Verifies a given message signature pair under a given public key. */ -int xmss_core_sign_open(unsigned char *m, unsigned long long *mlen, +int xmss_core_sign_open(const xmss_params *params, + unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { unsigned long long i; unsigned long idx = 0; - 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 wots_pk[params->wots_keysize]; + unsigned char pkhash[params->n]; + unsigned char root[params->n]; + unsigned char msg_h[params->n]; + unsigned char hash_key[3*params->n]; - unsigned char pub_seed[XMSS_N]; - memcpy(pub_seed, pk + XMSS_N, XMSS_N); + unsigned char pub_seed[params->n]; + memcpy(pub_seed, pk + params->n, params->n); // Init addresses uint32_t ots_addr[8] = {0}; @@ -171,37 +172,37 @@ int xmss_core_sign_open(unsigned char *m, unsigned long long *mlen, set_type(ltree_addr, 1); set_type(node_addr, 2); - *mlen = smlen - XMSS_BYTES; + *mlen = smlen - params->bytes; // Extract index - for (i = 0; i < XMSS_INDEX_LEN; i++) { - idx |= ((unsigned long long)sm[i]) << (8*(XMSS_INDEX_LEN - 1 - i)); + for (i = 0; i < params->index_len; i++) { + idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - i)); } // Generate hash key (R || root || idx) - memcpy(hash_key, sm + XMSS_INDEX_LEN, XMSS_N); - memcpy(hash_key + XMSS_N, pk, XMSS_N); - to_byte(hash_key + 2*XMSS_N, idx, XMSS_N); + memcpy(hash_key, sm + params->index_len, params->n); + memcpy(hash_key + params->n, pk, params->n); + to_byte(hash_key + 2*params->n, idx, params->n); // hash message - h_msg(msg_h, sm + XMSS_BYTES, *mlen, hash_key, 3*XMSS_N); - sm += XMSS_INDEX_LEN + XMSS_N; + h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n); + sm += params->index_len + params->n; // Prepare Address set_ots_addr(ots_addr, idx); // Check WOTS signature - wots_pk_from_sig(wots_pk, sm, msg_h, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; + wots_pk_from_sig(params, wots_pk, sm, msg_h, pub_seed, ots_addr); + sm += params->wots_keysize; // Compute Ltree set_ltree_addr(ltree_addr, idx); - l_tree(pkhash, wots_pk, pub_seed, ltree_addr); + l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr); // Compute root - validate_authpath(root, pkhash, idx, sm, pub_seed, node_addr); - sm += XMSS_TREEHEIGHT*XMSS_N; + validate_authpath(params, root, pkhash, idx, sm, pub_seed, node_addr); + sm += params->tree_height*params->n; - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { if (root[i] != pk[i]) { for (i = 0; i < *mlen; i++) { m[i] = 0; @@ -221,19 +222,20 @@ int xmss_core_sign_open(unsigned char *m, unsigned long long *mlen, /** * Verifies a given message signature pair under a given public key. */ -int xmssmt_core_sign_open(unsigned char *m, unsigned long long *mlen, +int xmssmt_core_sign_open(const xmss_params *params, + unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { uint32_t idx_leaf; unsigned long long i; unsigned long long idx = 0; - unsigned char wots_pk[XMSS_WOTS_KEYSIZE]; - unsigned char pkhash[XMSS_N]; - unsigned char root[XMSS_N]; + unsigned char wots_pk[params->wots_keysize]; + unsigned char pkhash[params->n]; + unsigned char root[params->n]; unsigned char *msg_h = root; - unsigned char hash_key[3*XMSS_N]; - const unsigned char *pub_seed = pk + XMSS_N; + unsigned char hash_key[3*params->n]; + const unsigned char *pub_seed = pk + params->n; // Init addresses uint32_t ots_addr[8] = {0}; @@ -244,26 +246,26 @@ int xmssmt_core_sign_open(unsigned char *m, unsigned long long *mlen, set_type(ltree_addr, 1); set_type(node_addr, 2); - *mlen = smlen - XMSS_BYTES; + *mlen = smlen - params->bytes; // Extract index - for (i = 0; i < XMSS_INDEX_LEN; i++) { - idx |= ((unsigned long long)sm[i]) << (8*(XMSS_INDEX_LEN - 1 - i)); + for (i = 0; i < params->index_len; i++) { + idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - i)); } // Generate hash key (R || root || idx) - memcpy(hash_key, sm + XMSS_INDEX_LEN, XMSS_N); - memcpy(hash_key + XMSS_N, pk, XMSS_N); - to_byte(hash_key + 2*XMSS_N, idx, XMSS_N); + memcpy(hash_key, sm + params->index_len, params->n); + memcpy(hash_key + params->n, pk, params->n); + to_byte(hash_key + 2*params->n, idx, params->n); // hash message - h_msg(msg_h, sm + XMSS_BYTES, *mlen, hash_key, 3*XMSS_N); - sm += XMSS_INDEX_LEN + XMSS_N; + h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n); + sm += params->index_len + params->n; - for (i = 0; i < XMSS_D; i++) { + for (i = 0; i < params->d; i++) { // Prepare Address - idx_leaf = (idx & ((1 << XMSS_TREEHEIGHT)-1)); - idx = idx >> XMSS_TREEHEIGHT; + idx_leaf = (idx & ((1 << params->tree_height)-1)); + idx = idx >> params->tree_height; set_layer_addr(ots_addr, i); set_layer_addr(ltree_addr, i); @@ -276,19 +278,19 @@ int xmssmt_core_sign_open(unsigned char *m, unsigned long long *mlen, set_ots_addr(ots_addr, idx_leaf); // Check WOTS signature - wots_pk_from_sig(wots_pk, sm, root, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; + wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr); + sm += params->wots_keysize; // Compute Ltree set_ltree_addr(ltree_addr, idx_leaf); - l_tree(pkhash, wots_pk, pub_seed, ltree_addr); + l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr); // Compute root - validate_authpath(root, pkhash, idx_leaf, sm, pub_seed, node_addr); - sm += XMSS_TREEHEIGHT*XMSS_N; + validate_authpath(params, root, pkhash, idx_leaf, sm, pub_seed, node_addr); + sm += params->tree_height*params->n; } - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { if (root[i] != pk[i]) { for (i = 0; i < *mlen; i++) { m[i] = 0; diff --git a/xmss_commons.h b/xmss_commons.h index a53ef8f..7d34013 100644 --- a/xmss_commons.h +++ b/xmss_commons.h @@ -9,26 +9,29 @@ Public domain. #include #include +#include "params.h" void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); void hexdump(const unsigned char *a, size_t len); -void gen_leaf_wots(unsigned char *leaf, +void gen_leaf_wots(const xmss_params *params, unsigned char *leaf, const unsigned char *sk_seed, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]); -void get_seed(unsigned char *seed, +void get_seed(const xmss_params *params, unsigned char *seed, const unsigned char *sk_seed, uint32_t addr[8]); -void l_tree(unsigned char *leaf, unsigned char *wots_pk, +void l_tree(const xmss_params *params, unsigned char *leaf, unsigned char *wots_pk, const unsigned char *pub_seed, uint32_t addr[8]); -int xmss_core_sign_open(unsigned char *m, unsigned long long *mlen, +int xmss_core_sign_open(const xmss_params *params, + unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); -int xmssmt_core_sign_open(unsigned char *m, unsigned long long *mlen, +int xmssmt_core_sign_open(const xmss_params *params, + unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); #endif diff --git a/xmss_core.c b/xmss_core.c index d302640..06ade46 100644 --- a/xmss_core.c +++ b/xmss_core.c @@ -22,7 +22,7 @@ Public domain. * Currently only used for key generation. * */ -static void treehash(unsigned char *node, uint32_t index, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) +static void treehash(const xmss_params *params, unsigned char *node, uint32_t index, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) { uint32_t idx = index; // use three different addresses because at this point we use all three formats in parallel @@ -39,27 +39,27 @@ static void treehash(unsigned char *node, uint32_t index, const unsigned char *s set_type(node_addr, 2); uint32_t lastnode, i; - unsigned char stack[(XMSS_TREEHEIGHT+1)*XMSS_N]; - uint16_t stacklevels[XMSS_TREEHEIGHT+1]; + unsigned char stack[(params->tree_height+1)*params->n]; + uint16_t stacklevels[params->tree_height+1]; unsigned int stackoffset=0; - lastnode = idx+(1 << XMSS_TREEHEIGHT); + lastnode = idx+(1 << params->tree_height); for (; idx < lastnode; idx++) { set_ltree_addr(ltree_addr, idx); set_ots_addr(ots_addr, idx); - gen_leaf_wots(stack+stackoffset*XMSS_N, sk_seed, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(params, stack+stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr); stacklevels[stackoffset] = 0; stackoffset++; while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { set_tree_height(node_addr, stacklevels[stackoffset-1]); set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); - hash_h(stack+(stackoffset-2)*XMSS_N, stack+(stackoffset-2)*XMSS_N, pub_seed, node_addr); + hash_h(params, stack+(stackoffset-2)*params->n, stack+(stackoffset-2)*params->n, pub_seed, node_addr); stacklevels[stackoffset-2]++; stackoffset--; } } - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { node[i] = stack[i]; } } @@ -69,11 +69,11 @@ static void treehash(unsigned char *node, uint32_t index, const unsigned char *s * 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, unsigned char *pub_seed, uint32_t addr[8]) +static void compute_authpath_wots(const xmss_params *params, 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; - unsigned char tree[2*(1<tree_height)*params->n]; uint32_t ots_addr[8]; uint32_t ltree_addr[8]; @@ -87,33 +87,33 @@ static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, set_type(node_addr, 2); // Compute all leaves - for (i = 0; i < (1U << XMSS_TREEHEIGHT); i++) { + for (i = 0; i < (1U << params->tree_height); i++) { set_ltree_addr(ltree_addr, i); set_ots_addr(ots_addr, i); - gen_leaf_wots(tree+((1<tree_height)*params->n + i*params->n), sk_seed, pub_seed, ltree_addr, ots_addr); } level = 0; // Compute tree: // Outer loop: For each inner layer - for (i = (1< 1; i>>=1) { + for (i = (1 << params->tree_height); i > 1; i>>=1) { set_tree_height(node_addr, level); // Inner loop: for each pair of sibling nodes for (j = 0; j < i; j+=2) { set_tree_index(node_addr, j>>1); - hash_h(tree + (i>>1)*XMSS_N + (j>>1) * XMSS_N, tree + i*XMSS_N + j*XMSS_N, pub_seed, node_addr); + hash_h(params, tree + (i>>1)*params->n + (j>>1) * params->n, tree + i*params->n + j*params->n, pub_seed, node_addr); } level++; } // copy authpath - 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); + for (i = 0; i < params->tree_height; i++) { + memcpy(authpath + i*params->n, tree + ((1 << params->tree_height)>>i)*params->n + ((leaf_idx >> i) ^ 1) * params->n, params->n); } // copy root -memcpy(root, tree+XMSS_N, XMSS_N); + memcpy(root, tree+params->n, params->n); } @@ -122,23 +122,23 @@ memcpy(root, tree+XMSS_N, XMSS_N); * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmss_core_keypair(unsigned char *pk, unsigned char *sk) +int xmss_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk) { // Set idx = 0 sk[0] = 0; sk[1] = 0; sk[2] = 0; sk[3] = 0; - // Init SK_SEED (XMSS_N byte), SK_PRF (XMSS_N byte), and PUB_SEED (XMSS_N byte) - randombytes(sk+4, 3*XMSS_N); + // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte) + randombytes(sk+4, 3*params->n); // Copy PUB_SEED to public key - memcpy(pk+XMSS_N, sk+4+2*XMSS_N, XMSS_N); + memcpy(pk+params->n, sk+4+2*params->n, params->n); uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Compute root - treehash(pk, 0, sk+4, sk+4+2*XMSS_N, addr); + treehash(params, pk, 0, sk+4, sk+4+2*params->n, addr); // copy root to sk - memcpy(sk+4+3*XMSS_N, pk, XMSS_N); + memcpy(sk+4+3*params->n, pk, params->n); return 0; } @@ -149,24 +149,24 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk) * 2. an updated secret key! * */ -int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) +int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) { 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[XMSS_N]; - unsigned char sk_prf[XMSS_N]; - unsigned char pub_seed[XMSS_N]; - unsigned char hash_key[3*XMSS_N]; + unsigned char sk_seed[params->n]; + unsigned char sk_prf[params->n]; + unsigned char pub_seed[params->n]; + unsigned char hash_key[3*params->n]; // index as 32 bytes string unsigned char idx_bytes_32[32]; to_byte(idx_bytes_32, idx, 32); - memcpy(sk_seed, sk+4, XMSS_N); - memcpy(sk_prf, sk+4+XMSS_N, XMSS_N); - memcpy(pub_seed, sk+4+2*XMSS_N, XMSS_N); + memcpy(sk_seed, sk+4, params->n); + memcpy(sk_prf, sk+4+params->n, params->n); + memcpy(pub_seed, sk+4+2*params->n, params->n); // Update SK sk[0] = ((idx + 1) >> 24) & 255; @@ -177,10 +177,10 @@ int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *sml // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // Init working params - unsigned char R[XMSS_N]; - unsigned char msg_h[XMSS_N]; - unsigned char root[XMSS_N]; - unsigned char ots_seed[XMSS_N]; + unsigned char R[params->n]; + unsigned char msg_h[params->n]; + unsigned char root[params->n]; + unsigned char ots_seed[params->n]; uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // --------------------------------- @@ -189,13 +189,13 @@ int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *sml // Message Hash: // First compute pseudorandom value - prf(R, idx_bytes_32, sk_prf, XMSS_N); + prf(params, R, idx_bytes_32, sk_prf, params->n); // Generate hash key (R || root || idx) - 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); + memcpy(hash_key, R, params->n); + memcpy(hash_key+params->n, sk+4+3*params->n, params->n); + to_byte(hash_key+2*params->n, idx, params->n); // Then use it for message digest - h_msg(msg_h, m, mlen, hash_key, 3*XMSS_N); + h_msg(params, msg_h, m, mlen, hash_key, 3*params->n); // Start collecting signature *smlen = 0; @@ -210,11 +210,11 @@ int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *sml *smlen += 4; // Copy R to signature - for (i = 0; i < XMSS_N; i++) + for (i = 0; i < params->n; i++) sm[i] = R[i]; - sm += XMSS_N; - *smlen += XMSS_N; + sm += params->n; + *smlen += params->n; // ---------------------------------- // Now we start to "really sign" @@ -225,17 +225,17 @@ int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *sml set_ots_addr(ots_addr, idx); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, ots_addr); + get_seed(params, ots_seed, sk_seed, ots_addr); // Compute WOTS signature - wots_sign(sm, msg_h, ots_seed, pub_seed, ots_addr); + wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; - *smlen += XMSS_WOTS_KEYSIZE; + sm += params->wots_keysize; + *smlen += params->wots_keysize; - compute_authpath_wots(root, sm, idx, sk_seed, pub_seed, ots_addr); - sm += XMSS_TREEHEIGHT*XMSS_N; - *smlen += XMSS_TREEHEIGHT*XMSS_N; + compute_authpath_wots(params, root, sm, idx, sk_seed, pub_seed, ots_addr); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; memcpy(sm, m, mlen); *smlen += mlen; @@ -248,25 +248,25 @@ int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *sml * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk) +int xmssmt_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk) { uint16_t i; // Set idx = 0 - for (i = 0; i < XMSS_INDEX_LEN; i++) { + for (i = 0; i < params->index_len; i++) { sk[i] = 0; } - // 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); + // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte) + randombytes(sk+params->index_len, 3*params->n); // Copy PUB_SEED to public key - memcpy(pk+XMSS_N, sk+XMSS_INDEX_LEN+2*XMSS_N, XMSS_N); + memcpy(pk+params->n, sk+params->index_len+2*params->n, params->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}; - set_layer_addr(addr, (XMSS_D-1)); + set_layer_addr(addr, (params->d-1)); // Compute root - treehash(pk, 0, sk+XMSS_INDEX_LEN, pk+XMSS_N, addr); - memcpy(sk+XMSS_INDEX_LEN+3*XMSS_N, pk, XMSS_N); + treehash(params, pk, 0, sk+params->index_len, pk+params->n, addr); + memcpy(sk+params->index_len+3*params->n, pk, params->n); return 0; } @@ -277,37 +277,37 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk) * 2. an updated secret key! * */ -int xmssmt_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) +int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) { uint64_t idx_tree; uint32_t idx_leaf; uint64_t i; - unsigned char sk_seed[XMSS_N]; - unsigned char sk_prf[XMSS_N]; - unsigned char pub_seed[XMSS_N]; + unsigned char sk_seed[params->n]; + unsigned char sk_prf[params->n]; + unsigned char pub_seed[params->n]; // Init working params - 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]; + unsigned char R[params->n]; + unsigned char hash_key[3*params->n]; + unsigned char msg_h[params->n]; + unsigned char root[params->n]; + unsigned char ots_seed[params->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 < XMSS_INDEX_LEN; i++) { - idx |= ((unsigned long long)sk[i]) << 8*(XMSS_INDEX_LEN - 1 - i); + for (i = 0; i < params->index_len; i++) { + idx |= ((unsigned long long)sk[i]) << 8*(params->index_len - 1 - i); } - 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); + memcpy(sk_seed, sk+params->index_len, params->n); + memcpy(sk_prf, sk+params->index_len+params->n, params->n); + memcpy(pub_seed, sk+params->index_len+2*params->n, params->n); // Update SK - for (i = 0; i < XMSS_INDEX_LEN; i++) { - sk[i] = ((idx + 1) >> 8*(XMSS_INDEX_LEN - 1 - i)) & 255; + for (i = 0; i < params->index_len; i++) { + sk[i] = ((idx + 1) >> 8*(params->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! @@ -320,33 +320,33 @@ int xmssmt_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *s // Message Hash: // First compute pseudorandom value to_byte(idx_bytes_32, idx, 32); - prf(R, idx_bytes_32, sk_prf, XMSS_N); + prf(params, R, idx_bytes_32, sk_prf, params->n); // Generate hash key (R || root || idx) - 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); + memcpy(hash_key, R, params->n); + memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n); + to_byte(hash_key+2*params->n, idx, params->n); // Then use it for message digest - h_msg(msg_h, m, mlen, hash_key, 3*XMSS_N); + h_msg(params, msg_h, m, mlen, hash_key, 3*params->n); // Start collecting signature *smlen = 0; // Copy index to signature - for (i = 0; i < XMSS_INDEX_LEN; i++) { - sm[i] = (idx >> 8*(XMSS_INDEX_LEN - 1 - i)) & 255; + for (i = 0; i < params->index_len; i++) { + sm[i] = (idx >> 8*(params->index_len - 1 - i)) & 255; } - sm += XMSS_INDEX_LEN; - *smlen += XMSS_INDEX_LEN; + sm += params->index_len; + *smlen += params->index_len; // Copy R to signature - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { sm[i] = R[i]; } - sm += XMSS_N; - *smlen += XMSS_N; + sm += params->n; + *smlen += params->n; // ---------------------------------- // Now we start to "really sign" @@ -356,47 +356,47 @@ int xmssmt_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *s // Prepare Address set_type(ots_addr, 0); - idx_tree = idx >> XMSS_TREEHEIGHT; - idx_leaf = (idx & ((1 << XMSS_TREEHEIGHT)-1)); + idx_tree = idx >> params->tree_height; + idx_leaf = (idx & ((1 << params->tree_height)-1)); set_layer_addr(ots_addr, 0); set_tree_addr(ots_addr, idx_tree); set_ots_addr(ots_addr, idx_leaf); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, ots_addr); + get_seed(params, ots_seed, sk_seed, ots_addr); // Compute WOTS signature - wots_sign(sm, msg_h, ots_seed, pub_seed, ots_addr); + wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; - *smlen += XMSS_WOTS_KEYSIZE; + sm += params->wots_keysize; + *smlen += params->wots_keysize; - compute_authpath_wots(root, sm, idx_leaf, sk_seed, pub_seed, ots_addr); - sm += XMSS_TREEHEIGHT*XMSS_N; - *smlen += XMSS_TREEHEIGHT*XMSS_N; + compute_authpath_wots(params, root, sm, idx_leaf, sk_seed, pub_seed, ots_addr); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; // Now loop over remaining layers... unsigned int j; - for (j = 1; j < XMSS_D; j++) { + for (j = 1; j < params->d; j++) { // Prepare Address - idx_leaf = (idx_tree & ((1 << XMSS_TREEHEIGHT)-1)); - idx_tree = idx_tree >> XMSS_TREEHEIGHT; + idx_leaf = (idx_tree & ((1 << params->tree_height)-1)); + idx_tree = idx_tree >> params->tree_height; set_layer_addr(ots_addr, j); set_tree_addr(ots_addr, idx_tree); set_ots_addr(ots_addr, idx_leaf); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, ots_addr); + get_seed(params, ots_seed, sk_seed, ots_addr); // Compute WOTS signature - wots_sign(sm, root, ots_seed, pub_seed, ots_addr); + wots_sign(params, sm, root, ots_seed, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; - *smlen += XMSS_WOTS_KEYSIZE; + sm += params->wots_keysize; + *smlen += params->wots_keysize; - compute_authpath_wots(root, sm, idx_leaf, sk_seed, pub_seed, ots_addr); - sm += XMSS_TREEHEIGHT*XMSS_N; - *smlen += XMSS_TREEHEIGHT*XMSS_N; + compute_authpath_wots(params, root, sm, idx_leaf, sk_seed, pub_seed, ots_addr); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; } memcpy(sm, m, mlen); diff --git a/xmss_core.h b/xmss_core.h index 39f0941..7f15b3b 100644 --- a/xmss_core.h +++ b/xmss_core.h @@ -15,7 +15,7 @@ Public domain. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmss_core_keypair(unsigned char *pk, unsigned char *sk); +int xmss_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk); /** * Signs a message. * Returns @@ -23,20 +23,20 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk); * 2. an updated secret key! * */ -int xmss_core_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen); +int xmss_core_sign(const xmss_params *params, 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_core_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk); +int xmss_core_sign_open(const xmss_params *params, 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_core_keypair(unsigned char *pk, unsigned char *sk); +int xmssmt_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk); /** * Signs a message. * Returns @@ -44,10 +44,10 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk); * 2. an updated secret key! * */ -int xmssmt_core_sign(unsigned char *sk, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen); +int xmssmt_core_sign(const xmss_params *params, 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_core_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk); +int xmssmt_core_sign_open(const xmss_params *params, 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_core_fast.c b/xmss_core_fast.c index d1c42a4..a1415a1 100644 --- a/xmss_core_fast.c +++ b/xmss_core_fast.c @@ -37,10 +37,11 @@ void xmss_set_bds_state(bds_state *state, unsigned char *stack, state->next_leaf = next_leaf; } -static int treehash_minheight_on_stack(bds_state* state, +static int treehash_minheight_on_stack(const xmss_params *params, + bds_state* state, const treehash_inst *treehash) { - unsigned int r = XMSS_TREEHEIGHT, i; + unsigned int r = params->tree_height, i; for (i = 0; i < treehash->stackusage; i++) { if (state->stacklevels[state->stackoffset - i - 1] < r) { @@ -55,7 +56,8 @@ static int treehash_minheight_on_stack(bds_state* state, * Currently only used for key generation. * */ -static void treehash_init(unsigned char *node, int height, int index, +static void treehash_init(const xmss_params *params, + 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]) { @@ -74,14 +76,14 @@ static void treehash_init(unsigned char *node, int height, int index, set_type(node_addr, 2); uint32_t lastnode, i; - unsigned char stack[(height+1)*XMSS_N]; + unsigned char stack[(height+1)*params->n]; unsigned int stacklevels[height+1]; unsigned int stackoffset=0; unsigned int nodeh; lastnode = idx+(1<tree_height-params->bds_k; i++) { state->treehash[i].h = i; state->treehash[i].completed = 1; state->treehash[i].stackusage = 0; @@ -91,40 +93,41 @@ static void treehash_init(unsigned char *node, int height, int index, for (; idx < lastnode; idx++) { set_ltree_addr(ltree_addr, idx); set_ots_addr(ots_addr, idx); - gen_leaf_wots(stack+stackoffset*XMSS_N, sk_seed, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(params, stack+stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr); stacklevels[stackoffset] = 0; stackoffset++; - if (XMSS_TREEHEIGHT - XMSS_BDS_K > 0 && i == 3) { - memcpy(state->treehash[0].node, stack+stackoffset*XMSS_N, XMSS_N); + if (params->tree_height - params->bds_k > 0 && i == 3) { + memcpy(state->treehash[0].node, stack+stackoffset*params->n, params->n); } while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { nodeh = stacklevels[stackoffset-1]; if (i >> nodeh == 1) { - memcpy(state->auth + nodeh*XMSS_N, stack+(stackoffset-1)*XMSS_N, XMSS_N); + memcpy(state->auth + nodeh*params->n, stack+(stackoffset-1)*params->n, params->n); } else { - if (nodeh < XMSS_TREEHEIGHT - XMSS_BDS_K && i >> nodeh == 3) { - memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*XMSS_N, XMSS_N); + if (nodeh < params->tree_height - params->bds_k && i >> nodeh == 3) { + memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*params->n, params->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); + else if (nodeh >= params->tree_height - params->bds_k) { + memcpy(state->retain + ((1 << (params->tree_height - 1 - nodeh)) + nodeh - params->tree_height + (((i >> nodeh) - 3) >> 1)) * params->n, stack+(stackoffset-1)*params->n, params->n); } } set_tree_height(node_addr, stacklevels[stackoffset-1]); set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); - hash_h(stack+(stackoffset-2)*XMSS_N, stack+(stackoffset-2)*XMSS_N, pub_seed, node_addr); + hash_h(params, stack+(stackoffset-2)*params->n, stack+(stackoffset-2)*params->n, pub_seed, node_addr); stacklevels[stackoffset-2]++; stackoffset--; } i++; } - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { node[i] = stack[i]; } } -static void treehash_update(treehash_inst *treehash, bds_state *state, +static void treehash_update(const xmss_params *params, + treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) @@ -144,25 +147,25 @@ static void treehash_update(treehash_inst *treehash, bds_state *state, set_ltree_addr(ltree_addr, treehash->next_idx); set_ots_addr(ots_addr, treehash->next_idx); - unsigned char nodebuffer[2 * XMSS_N]; + unsigned char nodebuffer[2 * params->n]; unsigned int nodeheight = 0; - gen_leaf_wots(nodebuffer, sk_seed, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(params, nodebuffer, sk_seed, pub_seed, ltree_addr, ots_addr); while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) { - memcpy(nodebuffer + XMSS_N, nodebuffer, XMSS_N); - memcpy(nodebuffer, state->stack + (state->stackoffset-1)*XMSS_N, XMSS_N); + memcpy(nodebuffer + params->n, nodebuffer, params->n); + memcpy(nodebuffer, state->stack + (state->stackoffset-1)*params->n, params->n); set_tree_height(node_addr, nodeheight); set_tree_index(node_addr, (treehash->next_idx >> (nodeheight+1))); - hash_h(nodebuffer, nodebuffer, pub_seed, node_addr); + hash_h(params, nodebuffer, nodebuffer, pub_seed, node_addr); nodeheight++; treehash->stackusage--; state->stackoffset--; } if (nodeheight == treehash->h) { // this also implies stackusage == 0 - memcpy(treehash->node, nodebuffer, XMSS_N); + memcpy(treehash->node, nodebuffer, params->n); treehash->completed = 1; } else { - memcpy(state->stack + state->stackoffset*XMSS_N, nodebuffer, XMSS_N); + memcpy(state->stack + state->stackoffset*params->n, nodebuffer, params->n); treehash->stackusage++; state->stacklevels[state->stackoffset] = nodeheight; state->stackoffset++; @@ -174,7 +177,8 @@ static void treehash_update(treehash_inst *treehash, bds_state *state, * 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, +static char bds_treehash_update(const xmss_params *params, + bds_state *state, unsigned int updates, const unsigned char *sk_seed, unsigned char *pub_seed, const uint32_t addr[8]) @@ -184,27 +188,27 @@ static char bds_treehash_update(bds_state *state, unsigned int updates, unsigned int used = 0; for (j = 0; j < updates; j++) { - l_min = XMSS_TREEHEIGHT; - level = XMSS_TREEHEIGHT - XMSS_BDS_K; - for (i = 0; i < XMSS_TREEHEIGHT - XMSS_BDS_K; i++) { + l_min = params->tree_height; + level = params->tree_height - params->bds_k; + for (i = 0; i < params->tree_height - params->bds_k; i++) { if (state->treehash[i].completed) { - low = XMSS_TREEHEIGHT; + low = params->tree_height; } else if (state->treehash[i].stackusage == 0) { low = i; } else { - low = treehash_minheight_on_stack(state, &(state->treehash[i])); + low = treehash_minheight_on_stack(params, state, &(state->treehash[i])); } if (low < l_min) { level = i; l_min = low; } } - if (level == XMSS_TREEHEIGHT - XMSS_BDS_K) { + if (level == params->tree_height - params->bds_k) { break; } - treehash_update(&(state->treehash[level]), state, sk_seed, pub_seed, addr); + treehash_update(params, &(state->treehash[level]), state, sk_seed, pub_seed, addr); used++; } return updates - used; @@ -214,7 +218,8 @@ static char bds_treehash_update(bds_state *state, unsigned int updates, * 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, +static char bds_state_update(const xmss_params *params, + bds_state *state, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8]) { @@ -224,7 +229,7 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, int nodeh; int idx = state->next_leaf; - if (idx == 1 << XMSS_TREEHEIGHT) { + if (idx == 1 << params->tree_height) { return 1; } @@ -240,29 +245,29 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, set_ots_addr(ots_addr, idx); set_ltree_addr(ltree_addr, idx); - gen_leaf_wots(state->stack+state->stackoffset*XMSS_N, sk_seed, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(params, state->stack+state->stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr); state->stacklevels[state->stackoffset] = 0; state->stackoffset++; - if (XMSS_TREEHEIGHT - XMSS_BDS_K > 0 && idx == 3) { - memcpy(state->treehash[0].node, state->stack+state->stackoffset*XMSS_N, XMSS_N); + if (params->tree_height - params->bds_k > 0 && idx == 3) { + memcpy(state->treehash[0].node, state->stack+state->stackoffset*params->n, params->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*XMSS_N, state->stack+(state->stackoffset-1)*XMSS_N, XMSS_N); + memcpy(state->auth + nodeh*params->n, state->stack+(state->stackoffset-1)*params->n, params->n); } else { - if (nodeh < XMSS_TREEHEIGHT - XMSS_BDS_K && idx >> nodeh == 3) { - memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*XMSS_N, XMSS_N); + if (nodeh < params->tree_height - params->bds_k && idx >> nodeh == 3) { + memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*params->n, params->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); + else if (nodeh >= params->tree_height - params->bds_k) { + memcpy(state->retain + ((1 << (params->tree_height - 1 - nodeh)) + nodeh - params->tree_height + (((idx >> nodeh) - 3) >> 1)) * params->n, state->stack+(state->stackoffset-1)*params->n, params->n); } } set_tree_height(node_addr, state->stacklevels[state->stackoffset-1]); set_tree_index(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); - hash_h(state->stack+(state->stackoffset-2)*XMSS_N, state->stack+(state->stackoffset-2)*XMSS_N, pub_seed, node_addr); + hash_h(params, state->stack+(state->stackoffset-2)*params->n, state->stack+(state->stackoffset-2)*params->n, pub_seed, node_addr); state->stacklevels[state->stackoffset-2]++; state->stackoffset--; @@ -276,15 +281,16 @@ static char bds_state_update(bds_state *state, const unsigned char *sk_seed, * 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, +static void bds_round(const xmss_params *params, + bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const unsigned char *pub_seed, uint32_t addr[8]) { unsigned int i; - unsigned int tau = XMSS_TREEHEIGHT; + unsigned int tau = params->tree_height; unsigned int startidx; unsigned int offset, rowidx; - unsigned char buf[2 * XMSS_N]; + unsigned char buf[2 * params->n]; uint32_t ots_addr[8]; uint32_t ltree_addr[8]; @@ -298,7 +304,7 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, memcpy(node_addr, addr, 12); set_type(node_addr, 2); - for (i = 0; i < XMSS_TREEHEIGHT; i++) { + for (i = 0; i < params->tree_height; i++) { if (! ((leaf_idx >> i) & 1)) { tau = i; break; @@ -306,36 +312,36 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, } if (tau > 0) { - memcpy(buf, state->auth + (tau-1) * XMSS_N, XMSS_N); + memcpy(buf, state->auth + (tau-1) * params->n, params->n); // we need to do this before refreshing state->keep to prevent overwriting - memcpy(buf + XMSS_N, state->keep + ((tau-1) >> 1) * XMSS_N, XMSS_N); + memcpy(buf + params->n, state->keep + ((tau-1) >> 1) * params->n, params->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 (!((leaf_idx >> (tau + 1)) & 1) && (tau < params->tree_height - 1)) { + memcpy(state->keep + (tau >> 1)*params->n, state->auth + tau*params->n, params->n); } if (tau == 0) { set_ltree_addr(ltree_addr, leaf_idx); set_ots_addr(ots_addr, leaf_idx); - gen_leaf_wots(state->auth, sk_seed, pub_seed, ltree_addr, ots_addr); + gen_leaf_wots(params, state->auth, sk_seed, pub_seed, ltree_addr, ots_addr); } else { set_tree_height(node_addr, (tau-1)); set_tree_index(node_addr, leaf_idx >> tau); - hash_h(state->auth + tau * XMSS_N, buf, pub_seed, node_addr); + hash_h(params, state->auth + tau * params->n, buf, pub_seed, node_addr); for (i = 0; i < tau; i++) { - if (i < XMSS_TREEHEIGHT - XMSS_BDS_K) { - memcpy(state->auth + i * XMSS_N, state->treehash[i].node, XMSS_N); + if (i < params->tree_height - params->bds_k) { + memcpy(state->auth + i * params->n, state->treehash[i].node, params->n); } else { - offset = (1 << (XMSS_TREEHEIGHT - 1 - i)) + i - XMSS_TREEHEIGHT; + offset = (1 << (params->tree_height - 1 - i)) + i - params->tree_height; rowidx = ((leaf_idx >> i) - 1) >> 1; - memcpy(state->auth + i * XMSS_N, state->retain + (offset + rowidx) * XMSS_N, XMSS_N); + memcpy(state->auth + i * params->n, state->retain + (offset + rowidx) * params->n, params->n); } } - for (i = 0; i < ((tau < XMSS_TREEHEIGHT - XMSS_BDS_K) ? tau : (XMSS_TREEHEIGHT - XMSS_BDS_K)); i++) { + for (i = 0; i < ((tau < params->tree_height - params->bds_k) ? tau : (params->tree_height - params->bds_k)); i++) { startidx = leaf_idx + 1 + 3 * (1 << i); - if (startidx < 1U << XMSS_TREEHEIGHT) { + if (startidx < 1U << params->tree_height) { state->treehash[i].h = i; state->treehash[i].next_idx = startidx; state->treehash[i].completed = 0; @@ -350,7 +356,8 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmss_core_keypair(unsigned char *pk, unsigned char *sk, bds_state *state) +int xmss_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk, bds_state *state) { uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -360,14 +367,14 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk, bds_state *state) sk[2] = 0; sk[3] = 0; // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) - randombytes(sk + XMSS_INDEX_LEN, 3*XMSS_N); + randombytes(sk + params->index_len, 3*params->n); // Copy PUB_SEED to public key - memcpy(pk + XMSS_N, sk + XMSS_INDEX_LEN + 2*XMSS_N, XMSS_N); + memcpy(pk + params->n, sk + params->index_len + 2*params->n, params->n); // Compute root - treehash_init(pk, XMSS_TREEHEIGHT, 0, state, sk + XMSS_INDEX_LEN, sk + XMSS_INDEX_LEN + 2*XMSS_N, addr); + treehash_init(params, pk, params->tree_height, 0, state, sk + params->index_len, sk + params->index_len + 2*params->n, addr); // copy root o sk - memcpy(sk + XMSS_INDEX_LEN + 3*XMSS_N, pk, XMSS_N); + memcpy(sk + params->index_len + 3*params->n, pk, params->n); return 0; } @@ -378,7 +385,8 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk, bds_state *state) * 2. an updated secret key! * */ -int xmss_core_sign(unsigned char *sk, bds_state *state, +int xmss_core_sign(const xmss_params *params, + unsigned char *sk, bds_state *state, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) { @@ -386,18 +394,18 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, // 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[XMSS_N]; - memcpy(sk_seed, sk + XMSS_INDEX_LEN, XMSS_N); - unsigned char sk_prf[XMSS_N]; - memcpy(sk_prf, sk + XMSS_INDEX_LEN + XMSS_N, XMSS_N); - unsigned char pub_seed[XMSS_N]; - memcpy(pub_seed, sk + XMSS_INDEX_LEN + 2*XMSS_N, XMSS_N); + unsigned char sk_seed[params->n]; + memcpy(sk_seed, sk + params->index_len, params->n); + unsigned char sk_prf[params->n]; + memcpy(sk_prf, sk + params->index_len + params->n, params->n); + unsigned char pub_seed[params->n]; + memcpy(pub_seed, sk + params->index_len + 2*params->n, params->n); // index as 32 bytes string unsigned char idx_bytes_32[32]; to_byte(idx_bytes_32, idx, 32); - unsigned char hash_key[3*XMSS_N]; + unsigned char hash_key[3*params->n]; // Update SK sk[0] = ((idx + 1) >> 24) & 255; @@ -408,9 +416,9 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, // -- A productive implementation should use a file handle instead and write the updated secret key at this point! // Init working params - unsigned char R[XMSS_N]; - unsigned char msg_h[XMSS_N]; - unsigned char ots_seed[XMSS_N]; + unsigned char R[params->n]; + unsigned char msg_h[params->n]; + unsigned char ots_seed[params->n]; uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // --------------------------------- @@ -419,13 +427,13 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, // Message Hash: // First compute pseudorandom value - prf(R, idx_bytes_32, sk_prf, XMSS_N); + prf(params, R, idx_bytes_32, sk_prf, params->n); // Generate hash key (R || root || idx) - 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); + memcpy(hash_key, R, params->n); + memcpy(hash_key+params->n, sk+4+3*params->n, params->n); + to_byte(hash_key+2*params->n, idx, params->n); // Then use it for message digest - h_msg(msg_h, m, mlen, hash_key, 3*XMSS_N); + h_msg(params, msg_h, m, mlen, hash_key, 3*params->n); // Start collecting signature *smlen = 0; @@ -440,12 +448,12 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, *smlen += 4; // Copy R to signature - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { sm[i] = R[i]; } - sm += XMSS_N; - *smlen += XMSS_N; + sm += params->n; + *smlen += params->n; // ---------------------------------- // Now we start to "really sign" @@ -456,24 +464,24 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, set_ots_addr(ots_addr, idx); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, ots_addr); + get_seed(params, ots_seed, sk_seed, ots_addr); // Compute WOTS signature - wots_sign(sm, msg_h, ots_seed, pub_seed, ots_addr); + wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; - *smlen += XMSS_WOTS_KEYSIZE; + sm += params->wots_keysize; + *smlen += params->wots_keysize; // the auth path was already computed during the previous round - memcpy(sm, state->auth, XMSS_TREEHEIGHT*XMSS_N); + memcpy(sm, state->auth, params->tree_height*params->n); - 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); + if (idx < (1U << params->tree_height) - 1) { + bds_round(params, state, idx, sk_seed, pub_seed, ots_addr); + bds_treehash_update(params, state, (params->tree_height - params->bds_k) >> 1, sk_seed, pub_seed, ots_addr); } - sm += XMSS_TREEHEIGHT*XMSS_N; - *smlen += XMSS_TREEHEIGHT*XMSS_N; + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; memcpy(sm, m, mlen); *smlen += mlen; @@ -486,35 +494,36 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk, +int xmssmt_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs) { - unsigned char ots_seed[XMSS_N]; + unsigned char ots_seed[params->n]; uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int i; // Set idx = 0 - for (i = 0; i < XMSS_INDEX_LEN; i++) { + for (i = 0; i < params->index_len; i++) { sk[i] = 0; } - // 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); + // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte) + randombytes(sk+params->index_len, 3*params->n); // Copy PUB_SEED to public key - memcpy(pk+XMSS_N, sk+XMSS_INDEX_LEN+2*XMSS_N, XMSS_N); + memcpy(pk+params->n, sk+params->index_len+2*params->n, params->n); // Start with the bottom-most layer set_layer_addr(addr, 0); // Set up state and compute wots signatures for all but topmost tree root - for (i = 0; i < XMSS_D - 1; i++) { + for (i = 0; i < params->d - 1; i++) { // Compute seed for OTS key pair - treehash_init(pk, XMSS_TREEHEIGHT, 0, states + i, sk+XMSS_INDEX_LEN, pk+XMSS_N, addr); + treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_len, pk+params->n, addr); set_layer_addr(addr, (i+1)); - get_seed(ots_seed, sk + XMSS_INDEX_LEN, addr); - wots_sign(wots_sigs + i*XMSS_WOTS_KEYSIZE, pk, ots_seed, pk+XMSS_N, addr); + get_seed(params, ots_seed, sk + params->index_len, addr); + wots_sign(params, wots_sigs + i*params->wots_keysize, pk, ots_seed, pk+params->n, addr); } // Address now points to the single tree on layer d-1 - treehash_init(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); + treehash_init(params, pk, params->tree_height, 0, states + i, sk+params->index_len, pk+params->n, addr); + memcpy(sk + params->index_len + 3*params->n, pk, params->n); return 0; } @@ -525,7 +534,8 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk, * 2. an updated secret key! * */ -int xmssmt_core_sign(unsigned char *sk, +int xmssmt_core_sign(const xmss_params *params, + unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) @@ -536,14 +546,14 @@ int xmssmt_core_sign(unsigned char *sk, int needswap_upto = -1; unsigned int updates; - unsigned char sk_seed[XMSS_N]; - unsigned char sk_prf[XMSS_N]; - unsigned char pub_seed[XMSS_N]; + unsigned char sk_seed[params->n]; + unsigned char sk_prf[params->n]; + unsigned char pub_seed[params->n]; // Init working params - unsigned char R[XMSS_N]; - unsigned char msg_h[XMSS_N]; - unsigned char hash_key[3*XMSS_N]; - unsigned char ots_seed[XMSS_N]; + unsigned char R[params->n]; + unsigned char msg_h[params->n]; + unsigned char hash_key[3*params->n]; + unsigned char ots_seed[params->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]; @@ -551,17 +561,17 @@ int xmssmt_core_sign(unsigned char *sk, // Extract SK unsigned long long idx = 0; - for (i = 0; i < XMSS_INDEX_LEN; i++) { - idx |= ((unsigned long long)sk[i]) << 8*(XMSS_INDEX_LEN - 1 - i); + for (i = 0; i < params->index_len; i++) { + idx |= ((unsigned long long)sk[i]) << 8*(params->index_len - 1 - i); } - 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); + memcpy(sk_seed, sk+params->index_len, params->n); + memcpy(sk_prf, sk+params->index_len+params->n, params->n); + memcpy(pub_seed, sk+params->index_len+2*params->n, params->n); // Update SK - for (i = 0; i < XMSS_INDEX_LEN; i++) { - sk[i] = ((idx + 1) >> 8*(XMSS_INDEX_LEN - 1 - i)) & 255; + for (i = 0; i < params->index_len; i++) { + sk[i] = ((idx + 1) >> 8*(params->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! @@ -574,33 +584,33 @@ int xmssmt_core_sign(unsigned char *sk, // Message Hash: // First compute pseudorandom value to_byte(idx_bytes_32, idx, 32); - prf(R, idx_bytes_32, sk_prf, XMSS_N); + prf(params, R, idx_bytes_32, sk_prf, params->n); // Generate hash key (R || root || idx) - 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); + memcpy(hash_key, R, params->n); + memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n); + to_byte(hash_key+2*params->n, idx, params->n); // Then use it for message digest - h_msg(msg_h, m, mlen, hash_key, 3*XMSS_N); + h_msg(params, msg_h, m, mlen, hash_key, 3*params->n); // Start collecting signature *smlen = 0; // Copy index to signature - for (i = 0; i < XMSS_INDEX_LEN; i++) { - sm[i] = (idx >> 8*(XMSS_INDEX_LEN - 1 - i)) & 255; + for (i = 0; i < params->index_len; i++) { + sm[i] = (idx >> 8*(params->index_len - 1 - i)) & 255; } - sm += XMSS_INDEX_LEN; - *smlen += XMSS_INDEX_LEN; + sm += params->index_len; + *smlen += params->index_len; // Copy R to signature - for (i = 0; i < XMSS_N; i++) { + for (i = 0; i < params->n; i++) { sm[i] = R[i]; } - sm += XMSS_N; - *smlen += XMSS_N; + sm += params->n; + *smlen += params->n; // ---------------------------------- // Now we start to "really sign" @@ -610,85 +620,85 @@ int xmssmt_core_sign(unsigned char *sk, // Prepare Address set_type(ots_addr, 0); - idx_tree = idx >> XMSS_TREEHEIGHT; - idx_leaf = (idx & ((1 << XMSS_TREEHEIGHT)-1)); + idx_tree = idx >> params->tree_height; + idx_leaf = (idx & ((1 << params->tree_height)-1)); set_layer_addr(ots_addr, 0); set_tree_addr(ots_addr, idx_tree); set_ots_addr(ots_addr, idx_leaf); // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, ots_addr); + get_seed(params, ots_seed, sk_seed, ots_addr); // Compute WOTS signature - wots_sign(sm, msg_h, ots_seed, pub_seed, ots_addr); + wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr); - sm += XMSS_WOTS_KEYSIZE; - *smlen += XMSS_WOTS_KEYSIZE; + sm += params->wots_keysize; + *smlen += params->wots_keysize; - memcpy(sm, states[0].auth, XMSS_TREEHEIGHT*XMSS_N); - sm += XMSS_TREEHEIGHT*XMSS_N; - *smlen += XMSS_TREEHEIGHT*XMSS_N; + memcpy(sm, states[0].auth, params->tree_height*params->n); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; // prepare signature of remaining layers - for (i = 1; i < XMSS_D; i++) { + for (i = 1; i < params->d; i++) { // put WOTS signature in place - memcpy(sm, wots_sigs + (i-1)*XMSS_WOTS_KEYSIZE, XMSS_WOTS_KEYSIZE); + memcpy(sm, wots_sigs + (i-1)*params->wots_keysize, params->wots_keysize); - sm += XMSS_WOTS_KEYSIZE; - *smlen += XMSS_WOTS_KEYSIZE; + sm += params->wots_keysize; + *smlen += params->wots_keysize; // put AUTH nodes in place - memcpy(sm, states[i].auth, XMSS_TREEHEIGHT*XMSS_N); - sm += XMSS_TREEHEIGHT*XMSS_N; - *smlen += XMSS_TREEHEIGHT*XMSS_N; + memcpy(sm, states[i].auth, params->tree_height*params->n); + sm += params->tree_height*params->n; + *smlen += params->tree_height*params->n; } - updates = (XMSS_TREEHEIGHT - XMSS_BDS_K) >> 1; + updates = (params->tree_height - params->bds_k) >> 1; set_tree_addr(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 << XMSS_TREEHEIGHT) + idx_leaf < (1ULL << XMSS_FULLHEIGHT)) { - bds_state_update(&states[XMSS_D], sk_seed, pub_seed, addr); + if ((1 + idx_tree) * (1 << params->tree_height) + idx_leaf < (1ULL << params->full_height)) { + bds_state_update(params, &states[params->d], sk_seed, pub_seed, addr); } - for (i = 0; i < XMSS_D; i++) { + for (i = 0; i < params->d; i++) { // check if we're not at the end of a tree - 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))); + if (! (((idx + 1) & ((1ULL << ((i+1)*params->tree_height)) - 1)) == 0)) { + idx_leaf = (idx >> (params->tree_height * i)) & ((1 << params->tree_height)-1); + idx_tree = (idx >> (params->tree_height * (i+1))); set_layer_addr(addr, i); set_tree_addr(addr, idx_tree); if (i == (unsigned int) (needswap_upto + 1)) { - bds_round(&states[i], idx_leaf, sk_seed, pub_seed, addr); + bds_round(params, &states[i], idx_leaf, sk_seed, pub_seed, addr); } - updates = bds_treehash_update(&states[i], updates, sk_seed, pub_seed, addr); + updates = bds_treehash_update(params, &states[i], updates, sk_seed, pub_seed, addr); set_tree_addr(addr, (idx_tree + 1)); // if a NEXT-tree exists for this level; - 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); + if ((1 + idx_tree) * (1 << params->tree_height) + idx_leaf < (1ULL << (params->full_height - params->tree_height * i))) { + if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << params->full_height)) { + bds_state_update(params, &states[params->d + i], sk_seed, pub_seed, addr); updates--; } } } - 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)); + else if (idx < (1ULL << params->full_height) - 1) { + memcpy(&tmp, states+params->d + i, sizeof(bds_state)); + memcpy(states+params->d + i, states + i, sizeof(bds_state)); memcpy(states + i, &tmp, sizeof(bds_state)); set_layer_addr(ots_addr, (i+1)); - set_tree_addr(ots_addr, ((idx + 1) >> ((i+2) * XMSS_TREEHEIGHT))); - set_ots_addr(ots_addr, (((idx >> ((i+1) * XMSS_TREEHEIGHT)) + 1) & ((1 << XMSS_TREEHEIGHT)-1))); + set_tree_addr(ots_addr, ((idx + 1) >> ((i+2) * params->tree_height))); + set_ots_addr(ots_addr, (((idx >> ((i+1) * params->tree_height)) + 1) & ((1 << params->tree_height)-1))); - get_seed(ots_seed, sk+XMSS_INDEX_LEN, ots_addr); - wots_sign(wots_sigs + i*XMSS_WOTS_KEYSIZE, states[i].stack, ots_seed, pub_seed, ots_addr); + get_seed(params, ots_seed, sk+params->index_len, ots_addr); + wots_sign(params, wots_sigs + i*params->wots_keysize, states[i].stack, ots_seed, pub_seed, ots_addr); - states[XMSS_D + i].stackoffset = 0; - states[XMSS_D + i].next_leaf = 0; + states[params->d + i].stackoffset = 0; + states[params->d + i].next_leaf = 0; updates--; // WOTS-signing counts as one update needswap_upto = i; - for (j = 0; j < XMSS_TREEHEIGHT-XMSS_BDS_K; j++) { + for (j = 0; j < params->tree_height-params->bds_k; j++) { states[i].treehash[j].completed = 1; } } diff --git a/xmss_core_fast.h b/xmss_core_fast.h index 01fa3dc..8afb678 100644 --- a/xmss_core_fast.h +++ b/xmss_core_fast.h @@ -8,6 +8,8 @@ Public domain. #ifndef XMSS_CORE_H #define XMSS_CORE_H +#include "params.h" + typedef struct{ unsigned int h; unsigned int next_idx; @@ -41,14 +43,16 @@ void xmss_set_bds_state(bds_state *state, unsigned char *stack, * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmss_core_keypair(unsigned char *pk, unsigned char *sk, bds_state *state); +int xmss_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk, bds_state *state); /** * Signs a message. * Returns * 1. an array containing the signature followed by the message AND * 2. an updated secret key! */ -int xmss_core_sign(unsigned char *sk, bds_state *state, +int xmss_core_sign(const xmss_params *params, + unsigned char *sk, bds_state *state, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen); /** @@ -56,7 +60,8 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, * * Note: msg and mlen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sm which has the form (sig||msg). */ -int xmss_core_sign_open(unsigned char *m, unsigned long long *mlen, +int xmss_core_sign_open(const xmss_params *params, + unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); @@ -65,7 +70,8 @@ int xmss_core_sign_open(unsigned char *m, unsigned long long *mlen, * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] * Format pk: [root || PUB_SEED] omitting algo oid. */ -int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk, +int xmssmt_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs); /** @@ -74,7 +80,8 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk, * 1. an array containing the signature followed by the message AND * 2. an updated secret key! */ -int xmssmt_core_sign(unsigned char *sk, +int xmssmt_core_sign(const xmss_params *params, + unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen); @@ -82,7 +89,8 @@ int xmssmt_core_sign(unsigned char *sk, /** * Verifies a given message signature pair under a given public key. */ -int xmssmt_core_sign_open(unsigned char *m, unsigned long long *mlen, +int xmssmt_core_sign_open(const xmss_params *params, + unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); #endif