Using global defines for parameters (as seems to be typical in academic crypto code) does not play nice with multithreading at all.master
@@ -2,11 +2,11 @@ CC = /usr/bin/gcc | |||||
CFLAGS = -Wall -g -O3 -Wextra | CFLAGS = -Wall -g -O3 -Wextra | ||||
all: test/test_wots \ | all: test/test_wots \ | ||||
test/test_xmss_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_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 | test/test_xmssmt | ||||
.PHONY: clean | .PHONY: clean | ||||
@@ -15,41 +15,34 @@ test/test_xmssmt | |||||
params_%.h: params.h.py | params_%.h: params.h.py | ||||
python3 params.h.py $(patsubst params_%.h,%,$@) > $@ | 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: | clean: | ||||
-rm test/test_wots | -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_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 | -rm test/test_xmssmt | ||||
distclean: clean | distclean: clean | ||||
@@ -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 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)._ | _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)._ | ||||
@@ -28,7 +28,8 @@ unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]) | |||||
return bytes; | 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 *key, unsigned int keylen, | ||||
const unsigned char *in, unsigned long long inlen, int n) | 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]; | 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); | 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); | 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); | 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); | shake256(out, 64, buf, inlen + keylen + n); | ||||
} | } | ||||
else { | else { | ||||
@@ -65,66 +66,70 @@ static int core_hash(unsigned char *out, const unsigned int type, | |||||
return 0; | 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) | 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 *in, unsigned long long inlen, | ||||
const unsigned char *key, const unsigned int keylen) | 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] | * 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]) | 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 char byte_addr[32]; | ||||
unsigned int i; | unsigned int i; | ||||
set_key_and_mask(addr, 0); | set_key_and_mask(addr, 0); | ||||
addr_to_byte(byte_addr, addr); | 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 | // Use MSB order | ||||
set_key_and_mask(addr, 1); | set_key_and_mask(addr, 1); | ||||
addr_to_byte(byte_addr, addr); | 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); | set_key_and_mask(addr, 2); | ||||
addr_to_byte(byte_addr, addr); | 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]; | 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]) | 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 char byte_addr[32]; | ||||
unsigned int i; | unsigned int i; | ||||
set_key_and_mask(addr, 0); | set_key_and_mask(addr, 0); | ||||
addr_to_byte(byte_addr, addr); | 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); | set_key_and_mask(addr, 1); | ||||
addr_to_byte(byte_addr, addr); | 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]; | 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); | |||||
} | } |
@@ -8,21 +8,27 @@ Public domain. | |||||
#ifndef HASH_H | #ifndef HASH_H | ||||
#define HASH_H | #define HASH_H | ||||
#include "params.h" | |||||
#define IS_LITTLE_ENDIAN 1 | #define IS_LITTLE_ENDIAN 1 | ||||
unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]); | 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); | 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 *in, unsigned long long inlen, | ||||
const unsigned char *key, const unsigned int keylen); | 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]); | 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]); | const unsigned char *pub_seed, uint32_t addr[8]); | ||||
#endif | #endif |
@@ -1,7 +1,7 @@ | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#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) { | switch (oid) { | ||||
case 0x01000001: | case 0x01000001: | ||||
@@ -10,7 +10,7 @@ int xmss_parse_oid(uint32_t oid) | |||||
case 0x04000004: | case 0x04000004: | ||||
case 0x05000005: | case 0x05000005: | ||||
case 0x06000006: | case 0x06000006: | ||||
XMSS_FUNC = XMSS_SHA2; | |||||
params->func = XMSS_SHA2; | |||||
break; | break; | ||||
case 0x07000007: | case 0x07000007: | ||||
@@ -19,7 +19,7 @@ int xmss_parse_oid(uint32_t oid) | |||||
case 0x0a00000a: | case 0x0a00000a: | ||||
case 0x0b00000b: | case 0x0b00000b: | ||||
case 0x0c00000c: | case 0x0c00000c: | ||||
XMSS_FUNC = XMSS_SHAKE; | |||||
params->func = XMSS_SHAKE; | |||||
break; | break; | ||||
default: | default: | ||||
@@ -33,7 +33,7 @@ int xmss_parse_oid(uint32_t oid) | |||||
case 0x07000007: | case 0x07000007: | ||||
case 0x08000008: | case 0x08000008: | ||||
case 0x09000009: | case 0x09000009: | ||||
XMSS_N = 32; | |||||
params->n = 32; | |||||
break; | break; | ||||
case 0x04000004: | case 0x04000004: | ||||
@@ -43,7 +43,7 @@ int xmss_parse_oid(uint32_t oid) | |||||
case 0x0a00000a: | case 0x0a00000a: | ||||
case 0x0b00000b: | case 0x0b00000b: | ||||
case 0x0c00000c: | case 0x0c00000c: | ||||
XMSS_N = 64; | |||||
params->n = 64; | |||||
break; | break; | ||||
default: | default: | ||||
@@ -54,53 +54,51 @@ int xmss_parse_oid(uint32_t oid) | |||||
case 0x04000004: | case 0x04000004: | ||||
case 0x07000007: | case 0x07000007: | ||||
case 0x0a00000a: | case 0x0a00000a: | ||||
XMSS_FULLHEIGHT = 10; | |||||
params->full_height = 10; | |||||
break; | break; | ||||
case 0x02000002: | case 0x02000002: | ||||
case 0x05000005: | case 0x05000005: | ||||
case 0x08000008: | case 0x08000008: | ||||
case 0x0b00000b: | case 0x0b00000b: | ||||
XMSS_FULLHEIGHT = 16; | |||||
params->full_height = 16; | |||||
break; | break; | ||||
case 0x03000003: | case 0x03000003: | ||||
case 0x06000006: | case 0x06000006: | ||||
case 0x09000009: | case 0x09000009: | ||||
case 0x0c00000c: | case 0x0c00000c: | ||||
XMSS_FULLHEIGHT = 20; | |||||
params->full_height = 20; | |||||
break; | break; | ||||
default: | default: | ||||
return 1; | 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 { | 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 | // TODO figure out sensible and legal values for this based on the above | ||||
XMSS_BDS_K = 0; | |||||
params->bds_k = 0; | |||||
return 0; | return 0; | ||||
} | } | ||||
int xmssmt_parse_oid(uint32_t oid) | |||||
int xmssmt_parse_oid(xmss_params *params, const uint32_t oid) | |||||
{ | { | ||||
switch (oid) { | switch (oid) { | ||||
case 0x01000001: | case 0x01000001: | ||||
@@ -119,7 +117,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x0e00000e: | case 0x0e00000e: | ||||
case 0x0f00000f: | case 0x0f00000f: | ||||
case 0x01010101: | case 0x01010101: | ||||
XMSS_FUNC = XMSS_SHA2; | |||||
params->func = XMSS_SHA2; | |||||
break; | break; | ||||
case 0x02010102: | case 0x02010102: | ||||
@@ -138,7 +136,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x0f01010f: | case 0x0f01010f: | ||||
case 0x01020201: | case 0x01020201: | ||||
case 0x02020202: | case 0x02020202: | ||||
XMSS_FUNC = XMSS_SHAKE; | |||||
params->func = XMSS_SHAKE; | |||||
break; | break; | ||||
default: | default: | ||||
@@ -162,7 +160,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x07010107: | case 0x07010107: | ||||
case 0x08010108: | case 0x08010108: | ||||
case 0x09010109: | case 0x09010109: | ||||
XMSS_N = 32; | |||||
params->n = 32; | |||||
break; | break; | ||||
case 0x09000009: | case 0x09000009: | ||||
@@ -182,7 +180,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x0f01010f: | case 0x0f01010f: | ||||
case 0x01020201: | case 0x01020201: | ||||
case 0x02020202: | case 0x02020202: | ||||
XMSS_N = 64; | |||||
params->n = 64; | |||||
break; | break; | ||||
default: | default: | ||||
@@ -200,7 +198,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x0a01010a: | case 0x0a01010a: | ||||
case 0x0b01010b: | case 0x0b01010b: | ||||
XMSS_FULLHEIGHT = 20; | |||||
params->full_height = 20; | |||||
break; | break; | ||||
case 0x03000003: | case 0x03000003: | ||||
@@ -218,7 +216,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x0c01010c: | case 0x0c01010c: | ||||
case 0x0d01010d: | case 0x0d01010d: | ||||
case 0x0e01010e: | case 0x0e01010e: | ||||
XMSS_FULLHEIGHT = 40; | |||||
params->full_height = 40; | |||||
break; | break; | ||||
case 0x06000006: | case 0x06000006: | ||||
@@ -236,7 +234,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x0f01010f: | case 0x0f01010f: | ||||
case 0x01020201: | case 0x01020201: | ||||
case 0x02020202: | case 0x02020202: | ||||
XMSS_FULLHEIGHT = 60; | |||||
params->full_height = 60; | |||||
break; | break; | ||||
default: | default: | ||||
@@ -251,7 +249,7 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x04010104: | case 0x04010104: | ||||
case 0x0a01010a: | case 0x0a01010a: | ||||
case 0x0c01010c: | case 0x0c01010c: | ||||
XMSS_D = 2; | |||||
params->d = 2; | |||||
break; | break; | ||||
case 0x02000002: | case 0x02000002: | ||||
@@ -262,62 +260,60 @@ int xmssmt_parse_oid(uint32_t oid) | |||||
case 0x05010105: | case 0x05010105: | ||||
case 0x0b01010b: | case 0x0b01010b: | ||||
case 0x0d01010d: | case 0x0d01010d: | ||||
XMSS_D = 4; | |||||
params->d = 4; | |||||
break; | break; | ||||
case 0x05000005: | case 0x05000005: | ||||
case 0x0d00000d: | case 0x0d00000d: | ||||
case 0x06010106: | case 0x06010106: | ||||
case 0x0e01010e: | case 0x0e01010e: | ||||
XMSS_D = 8; | |||||
params->d = 8; | |||||
break; | break; | ||||
case 0x06000006: | case 0x06000006: | ||||
case 0x0e00000e: | case 0x0e00000e: | ||||
case 0x07010107: | case 0x07010107: | ||||
case 0x0f01010f: | case 0x0f01010f: | ||||
XMSS_D = 3; | |||||
params->d = 3; | |||||
break; | break; | ||||
case 0x07000007: | case 0x07000007: | ||||
case 0x0f00000f: | case 0x0f00000f: | ||||
case 0x08010108: | case 0x08010108: | ||||
case 0x01020201: | case 0x01020201: | ||||
XMSS_D = 6; | |||||
params->d = 6; | |||||
break; | break; | ||||
case 0x08000008: | case 0x08000008: | ||||
case 0x01010101: | case 0x01010101: | ||||
case 0x09010109: | case 0x09010109: | ||||
case 0x02020202: | case 0x02020202: | ||||
XMSS_D = 12; | |||||
params->d = 12; | |||||
break; | break; | ||||
default: | default: | ||||
return 1; | 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 { | 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 | // TODO figure out sensible and legal values for this based on the above | ||||
XMSS_BDS_K = 0; | |||||
params->bds_k = 0; | |||||
return 0; | return 0; | ||||
} | } |
@@ -1,32 +0,0 @@ | |||||
#ifndef PARAMS_H | |||||
#define PARAMS_H | |||||
#include <stdint.h> | |||||
// 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 |
@@ -14,27 +14,32 @@ static void hexdump(unsigned char *a, size_t len) | |||||
int main() | 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 pk1[sig_len]; | ||||
unsigned char pk2[sig_len]; | unsigned char pk2[sig_len]; | ||||
unsigned char sig[sig_len]; | unsigned char sig[sig_len]; | ||||
uint32_t addr[8] = {1,2,3,4}; | uint32_t addr[8] = {1,2,3,4}; | ||||
unsigned char msg[XMSS_N]; | |||||
unsigned char msg[params.n]; | |||||
int i; | 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); | //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++) | for (i = 0; i < sig_len; i++) | ||||
if (pk1[i] != pk2[i]) { | if (pk1[i] != pk2[i]) { | ||||
@@ -15,26 +15,27 @@ unsigned long long mlen; | |||||
int main() | int main() | ||||
{ | { | ||||
xmss_params params; | |||||
// TODO test more different OIDs | // TODO test more different OIDs | ||||
uint32_t oid = 0x01000001; | uint32_t oid = 0x01000001; | ||||
xmss_parse_oid(oid); // Parse it to make sure the sizes are set | |||||
xmss_parse_oid(¶ms, oid); | |||||
int r; | int r; | ||||
unsigned long long i, j; | unsigned long long i, j; | ||||
unsigned long errors = 0; | 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"); | printf("keypair\n"); | ||||
xmss_keypair(pk, sk, oid); | xmss_keypair(pk, sk, oid); | ||||
// check pub_seed in SK | // 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 | // check index | ||||
@@ -54,7 +55,7 @@ int main() | |||||
} | } | ||||
printf("\n"); | printf("\n"); | ||||
r = memcmp(mi, sm+XMSS_BYTES,MLEN); | |||||
r = memcmp(mi, sm+params.bytes,MLEN); | |||||
printf("%d\n", r); | printf("%d\n", r); | ||||
/* Test valid signature */ | /* Test valid signature */ | ||||
@@ -67,7 +68,7 @@ int main() | |||||
printf("%llu\n", MLEN-mlen); | printf("%llu\n", MLEN-mlen); | ||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[XMSS_BYTES+10] ^= 1; | |||||
sm[params.bytes+10] ^= 1; | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | ||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
@@ -77,7 +78,7 @@ int main() | |||||
/* Test with modified signature */ | /* Test with modified signature */ | ||||
/* Modified index */ | /* Modified index */ | ||||
sm[XMSS_BYTES+10] ^= 1; | |||||
sm[params.bytes+10] ^= 1; | |||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | ||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
@@ -108,7 +109,7 @@ int main() | |||||
/* Modified AUTH */ | /* Modified AUTH */ | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
sm[XMSS_BYTES - 10] ^= 1; | |||||
sm[params.bytes - 10] ^= 1; | |||||
r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | r = xmss_sign_open(mo, &mlen, sm, smlen, pk); | ||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
@@ -14,23 +14,28 @@ unsigned long long mlen; | |||||
int main() | int main() | ||||
{ | { | ||||
xmss_params params; | |||||
// TODO test more different OIDs | |||||
uint32_t oid = 0x01000001; | |||||
xmss_parse_oid(¶ms, oid); | |||||
int r; | int r; | ||||
unsigned long long i, j; | unsigned long long i, j; | ||||
unsigned long errors = 0; | 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 mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
printf("keypair\n"); | printf("keypair\n"); | ||||
xmss_core_keypair(pk, sk); | |||||
xmss_core_keypair(¶ms, pk, sk); | |||||
// check pub_seed in 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 | // check index | ||||
@@ -41,7 +46,7 @@ int main() | |||||
randombytes(mi, MLEN); | randombytes(mi, MLEN); | ||||
printf("sign\n"); | 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]; | idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | ||||
printf("\nidx = %lu\n",idx); | printf("\nidx = %lu\n",idx); | ||||
@@ -55,7 +60,7 @@ int main() | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | 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); | printf("%d\n", r); | ||||
if (r != 0) errors++; | if (r != 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -64,7 +69,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[signature_length+10] ^= 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); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -75,7 +80,7 @@ int main() | |||||
/* Modified index */ | /* Modified index */ | ||||
sm[signature_length+10] ^= 1; | sm[signature_length+10] ^= 1; | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); | |||||
r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -85,7 +90,7 @@ int main() | |||||
/* Modified R */ | /* Modified R */ | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
sm[5] ^= 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); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -95,7 +100,7 @@ int main() | |||||
/* Modified OTS sig */ | /* Modified OTS sig */ | ||||
sm[5] ^= 1; | sm[5] ^= 1; | ||||
sm[240] ^= 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); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -105,7 +110,7 @@ int main() | |||||
/* Modified AUTH */ | /* Modified AUTH */ | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
sm[signature_length - 10] ^= 1; | sm[signature_length - 10] ^= 1; | ||||
r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); | |||||
r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -20,31 +20,36 @@ unsigned long long cpucycles(void) | |||||
int main() | int main() | ||||
{ | { | ||||
xmss_params params; | |||||
// TODO test more different OIDs | |||||
uint32_t oid = 0x01000001; | |||||
xmss_parse_oid(¶ms, oid); | |||||
int r; | int r; | ||||
unsigned long long i; | unsigned long long i; | ||||
unsigned int k = XMSS_BDS_K; | |||||
unsigned int k = params.bds_k; | |||||
unsigned long errors = 0; | 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? | // 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 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 s; | ||||
bds_state *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); | 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 mi[MLEN]; | ||||
unsigned char mo[MLEN+signature_length]; | unsigned char mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
@@ -55,15 +60,15 @@ int main() | |||||
printf("keypair\n"); | printf("keypair\n"); | ||||
t1 = cpucycles(); | t1 = cpucycles(); | ||||
xmss_core_keypair(pk, sk, state); | |||||
xmss_core_keypair(¶ms, pk, sk, state); | |||||
t2 = cpucycles(); | t2 = cpucycles(); | ||||
printf("cycles = %llu\n", (t2-t1)); | printf("cycles = %llu\n", (t2-t1)); | ||||
double sec = (t2-t1)/3500000; | double sec = (t2-t1)/3500000; | ||||
printf("ms = %f\n", sec); | printf("ms = %f\n", sec); | ||||
// check pub_seed in 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 | // check index | ||||
@@ -72,7 +77,7 @@ int main() | |||||
for (i = 0; i < SIGNATURES; i++) { | for (i = 0; i < SIGNATURES; i++) { | ||||
printf("sign\n"); | 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]; | idx = ((unsigned long)sm[0] << 24) | ((unsigned long)sm[1] << 16) | ((unsigned long)sm[2] << 8) | sm[3]; | ||||
printf("\nidx = %lu\n",idx); | printf("\nidx = %lu\n",idx); | ||||
@@ -81,7 +86,7 @@ int main() | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | 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); | printf("%d\n", r); | ||||
if (r != 0) errors++; | if (r != 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -90,7 +95,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[signature_length+10] ^= 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); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -101,7 +106,7 @@ int main() | |||||
/* Modified index */ | /* Modified index */ | ||||
sm[signature_length+10] ^= 1; | sm[signature_length+10] ^= 1; | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); | |||||
r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -111,7 +116,7 @@ int main() | |||||
/* Modified R */ | /* Modified R */ | ||||
sm[2] ^= 1; | sm[2] ^= 1; | ||||
sm[5] ^= 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); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -121,7 +126,7 @@ int main() | |||||
/* Modified OTS sig */ | /* Modified OTS sig */ | ||||
sm[5] ^= 1; | sm[5] ^= 1; | ||||
sm[240] ^= 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); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -131,7 +136,7 @@ int main() | |||||
/* Modified AUTH */ | /* Modified AUTH */ | ||||
sm[240] ^= 1; | sm[240] ^= 1; | ||||
sm[signature_length - 10] ^= 1; | sm[signature_length - 10] ^= 1; | ||||
r = xmss_core_sign_open(mo, &mlen, sm, smlen, pk); | |||||
r = xmss_core_sign_open(¶ms, mo, &mlen, sm, smlen, pk); | |||||
printf("%d\n", r+1); | printf("%d\n", r+1); | ||||
if (r == 0) errors++; | if (r == 0) errors++; | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
@@ -15,33 +15,34 @@ unsigned long long mlen; | |||||
int main() | int main() | ||||
{ | { | ||||
xmss_params params; | |||||
// TODO test more different OIDs | // TODO test more different OIDs | ||||
uint32_t oid = 0x01000001; | uint32_t oid = 0x01000001; | ||||
xmssmt_parse_oid(oid); // Parse it to make sure the sizes are set | |||||
xmssmt_parse_oid(¶ms, oid); | |||||
int r; | int r; | ||||
unsigned long long i,j; | 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"); | printf("keypair\n"); | ||||
xmssmt_keypair(pk, sk, oid); | xmssmt_keypair(pk, sk, oid); | ||||
// check pub_seed in SK | // 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"); | printf("pk checked\n"); | ||||
// check index | // check index | ||||
unsigned long long idx = 0; | 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); | if (idx) printf("\nidx != 0: %llu\n",idx); | ||||
@@ -52,11 +53,11 @@ int main() | |||||
printf("sign\n"); | printf("sign\n"); | ||||
xmssmt_sign(sk, sm, &smlen, mi, MLEN); | xmssmt_sign(sk, sm, &smlen, mi, MLEN); | ||||
idx = 0; | 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); | printf("\nidx = %llu\n",idx); | ||||
r = memcmp(mi, sm+XMSS_BYTES,MLEN); | |||||
r = memcmp(mi, sm+params.bytes,MLEN); | |||||
printf("%d\n", r); | printf("%d\n", r); | ||||
for (j = 0; j < smlen; j++) { | for (j = 0; j < smlen; j++) { | ||||
@@ -14,26 +14,31 @@ unsigned long long mlen; | |||||
int main() | int main() | ||||
{ | { | ||||
xmss_params params; | |||||
// TODO test more different OIDs | |||||
uint32_t oid = 0x01000001; | |||||
xmssmt_parse_oid(¶ms, oid); | |||||
int r; | int r; | ||||
unsigned long long i,j; | 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 mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
printf("keypair\n"); | printf("keypair\n"); | ||||
xmssmt_core_keypair(pk, sk); | |||||
xmssmt_core_keypair(¶ms, pk, sk); | |||||
// check pub_seed in 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"); | printf("pk checked\n"); | ||||
unsigned int idx_len = XMSS_INDEX_LEN; | |||||
unsigned int idx_len = params.index_len; | |||||
// check index | // check index | ||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
@@ -46,7 +51,7 @@ int main() | |||||
randombytes(mi, MLEN); | randombytes(mi, MLEN); | ||||
printf("sign\n"); | printf("sign\n"); | ||||
xmssmt_core_sign(sk, sm, &smlen, mi, MLEN); | |||||
xmssmt_core_sign(¶ms, sk, sm, &smlen, mi, MLEN); | |||||
idx = 0; | idx = 0; | ||||
for (j = 0; j < idx_len; j++) { | for (j = 0; j < idx_len; j++) { | ||||
idx += ((unsigned long long)sm[j]) << 8*(idx_len - 1 - j); | idx += ((unsigned long long)sm[j]) << 8*(idx_len - 1 - j); | ||||
@@ -62,7 +67,7 @@ int main() | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | 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); | printf("%d\n", r); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", r); | printf("%d\n", r); | ||||
@@ -70,7 +75,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[52] ^= 1; | 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); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
@@ -80,7 +85,7 @@ int main() | |||||
sm[260] ^= 1; | sm[260] ^= 1; | ||||
sm[52] ^= 1; | sm[52] ^= 1; | ||||
sm[2] ^= 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); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
@@ -23,12 +23,17 @@ unsigned long long cpucycles(void) | |||||
int main() | int main() | ||||
{ | { | ||||
xmss_params params; | |||||
// TODO test more different OIDs | |||||
uint32_t oid = 0x01000001; | |||||
xmssmt_parse_oid(¶ms, oid); | |||||
int r; | int r; | ||||
unsigned long long i,j; | 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; | unsigned int tree_h = h / d; | ||||
@@ -40,7 +45,7 @@ int main() | |||||
treehash_inst treehash[(2*d-1) * (tree_h-k)]; | treehash_inst treehash[(2*d-1) * (tree_h-k)]; | ||||
unsigned char th_nodes[(2*d-1) * (tree_h-k)*n]; | unsigned char th_nodes[(2*d-1) * (tree_h-k)*n]; | ||||
unsigned char retain[(2*d-1) * ((1 << k) - k - 1)*n]; | unsigned char retain[(2*d-1) * ((1 << k) - k - 1)*n]; | ||||
unsigned char wots_sigs[d * 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' | // first d are 'regular' states, second d are 'next'; top tree has no 'next' | ||||
bds_state states[2*d-1]; | bds_state states[2*d-1]; | ||||
@@ -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 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 mo[MLEN+signature_length]; | ||||
unsigned char sm[MLEN+signature_length]; | unsigned char sm[MLEN+signature_length]; | ||||
randombytes(mi, MLEN); | randombytes(mi, MLEN); | ||||
printf("keypair\n"); | 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 | // check pub_seed in SK | ||||
for (i = 0; i < n; i++) { | 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"); | printf("pk checked\n"); | ||||
unsigned int idx_len = XMSS_INDEX_LEN; | |||||
unsigned int idx_len = params.index_len; | |||||
// check index | // check index | ||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < idx_len; i++) { | for (i = 0; i < idx_len; i++) { | ||||
@@ -87,7 +92,7 @@ int main() | |||||
for (i = 0; i < SIGNATURES; i++) { | for (i = 0; i < SIGNATURES; i++) { | ||||
printf("sign\n"); | printf("sign\n"); | ||||
t1 = cpucycles(); | 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(); | t2 = cpucycles(); | ||||
printf("signing cycles = %llu\n", (t2-t1)); | printf("signing cycles = %llu\n", (t2-t1)); | ||||
@@ -102,7 +107,7 @@ int main() | |||||
/* Test valid signature */ | /* Test valid signature */ | ||||
printf("verify\n"); | printf("verify\n"); | ||||
t1 = cpucycles(); | 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(); | t2 = cpucycles(); | ||||
printf("verification cycles = %llu\n", (t2-t1)); | printf("verification cycles = %llu\n", (t2-t1)); | ||||
printf("%d\n", r); | printf("%d\n", r); | ||||
@@ -112,7 +117,7 @@ int main() | |||||
/* Test with modified message */ | /* Test with modified message */ | ||||
sm[52] ^= 1; | 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); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
@@ -122,7 +127,7 @@ int main() | |||||
sm[260] ^= 1; | sm[260] ^= 1; | ||||
sm[52] ^= 1; | sm[52] ^= 1; | ||||
sm[2] ^= 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); | printf("%d\n", r+1); | ||||
r = memcmp(mi,mo,MLEN); | r = memcmp(mi,mo,MLEN); | ||||
printf("%d\n", (r!=0) - 1); | printf("%d\n", (r!=0) - 1); | ||||
@@ -17,14 +17,15 @@ Public domain. | |||||
* Expands an n-byte array into a len*n byte array | * Expands an n-byte array into a len*n byte array | ||||
* this is done using PRF | * this is done using PRF | ||||
*/ | */ | ||||
static void expand_seed(unsigned char *outseeds, const unsigned char *inseed) | |||||
static void expand_seed(const xmss_params *params, | |||||
unsigned char *outseeds, const unsigned char *inseed) | |||||
{ | { | ||||
uint32_t i; | uint32_t i; | ||||
unsigned char ctr[32]; | 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); | 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 | * interpretes in as start-th value of the chain | ||||
* addr has to contain the address of the chain | * addr has to contain the address of the chain | ||||
*/ | */ | ||||
static void gen_chain(unsigned char *out, const unsigned char *in, | |||||
static void gen_chain(const xmss_params *params, | |||||
unsigned char *out, const unsigned char *in, | |||||
unsigned int start, unsigned int steps, | unsigned int start, unsigned int steps, | ||||
const unsigned char *pub_seed, uint32_t addr[8]) | const unsigned char *pub_seed, uint32_t addr[8]) | ||||
{ | { | ||||
uint32_t i; | uint32_t i; | ||||
for (i = 0; i < XMSS_N; i++) { | |||||
for (i = 0; i < params->n; i++) { | |||||
out[i] = in[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); | 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. | * 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 in = 0; | ||||
int out = 0; | int out = 0; | ||||
@@ -68,87 +71,89 @@ static void base_w(int *output, const int out_len, const unsigned char *input) | |||||
in++; | in++; | ||||
bits += 8; | 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++; | 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]) | const unsigned char *pub_seed, uint32_t addr[8]) | ||||
{ | { | ||||
uint32_t i; | 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); | 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, | const unsigned char *sk, const unsigned char *pub_seed, | ||||
uint32_t addr[8]) | uint32_t addr[8]) | ||||
{ | { | ||||
int basew[XMSS_WOTS_LEN]; | |||||
int basew[params->wots_len]; | |||||
int csum = 0; | 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; | 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); | 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); | 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 *sig, const unsigned char *msg, | ||||
const unsigned char *pub_seed, uint32_t addr[8]) | const unsigned char *pub_seed, uint32_t addr[8]) | ||||
{ | { | ||||
int basew[XMSS_WOTS_LEN]; | |||||
int basew[params->wots_len]; | |||||
int csum = 0; | 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; | 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); | 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); | |||||
} | } | ||||
} | } |
@@ -9,6 +9,7 @@ Public domain. | |||||
#define WOTS_H | #define WOTS_H | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#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. | * 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. | * 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]); | const unsigned char *pub_seed, uint32_t addr[8]); | ||||
/** | /** | ||||
* Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig". | * Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig". | ||||
*/ | */ | ||||
void wots_sign(unsigned char *sig, const unsigned char *msg, | |||||
void wots_sign(const xmss_params *params, | |||||
unsigned char *sig, const unsigned char *msg, | |||||
const unsigned char *sk, const unsigned char *pub_seed, | const unsigned char *sk, const unsigned char *pub_seed, | ||||
uint32_t addr[8]); | uint32_t addr[8]); | ||||
/** | /** | ||||
* Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk. | * Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk. | ||||
*/ | */ | ||||
void wots_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 *sig, const unsigned char *msg, | ||||
const unsigned char *pub_seed, uint32_t addr[8]); | const unsigned char *pub_seed, uint32_t addr[8]); | ||||
@@ -1,6 +1,6 @@ | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include "params_runtime.h" | |||||
#include "params.h" | |||||
#include "xmss_core.h" | #include "xmss_core.h" | ||||
/* This file provides wrapper functions that take keys that include OIDs to | /* 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) | int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) | ||||
{ | { | ||||
xmss_params params; | |||||
unsigned int i; | unsigned int i; | ||||
if (xmss_parse_oid(oid)) { | |||||
if (xmss_parse_oid(¶ms, oid)) { | |||||
return 1; | return 1; | ||||
} | } | ||||
for (i = 0; i < XMSS_OID_LEN; i++) { | for (i = 0; i < XMSS_OID_LEN; i++) { | ||||
pk[i] = (oid >> (8 * i)) & 0xFF; | pk[i] = (oid >> (8 * i)) & 0xFF; | ||||
/* For an implementation that uses runtime parameters, it is crucial | /* 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; | 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, | int xmss_sign(unsigned char *sk, | ||||
unsigned char *sm, unsigned long long *smlen, | unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen) | const unsigned char *m, unsigned long long mlen) | ||||
{ | { | ||||
xmss_params params; | |||||
uint32_t oid = 0; | uint32_t oid = 0; | ||||
unsigned int i; | unsigned int i; | ||||
for (i = 0; i < XMSS_OID_LEN; i++) { | for (i = 0; i < XMSS_OID_LEN; i++) { | ||||
oid |= sk[i] << (i * 8); | oid |= sk[i] << (i * 8); | ||||
} | } | ||||
if (xmss_parse_oid(oid)) { | |||||
if (xmss_parse_oid(¶ms, oid)) { | |||||
return 1; | 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, | int xmss_sign_open(unsigned char *m, unsigned long long *mlen, | ||||
const unsigned char *sm, unsigned long long smlen, | const unsigned char *sm, unsigned long long smlen, | ||||
const unsigned char *pk) | const unsigned char *pk) | ||||
{ | { | ||||
xmss_params params; | |||||
uint32_t oid = 0; | uint32_t oid = 0; | ||||
unsigned int i; | unsigned int i; | ||||
for (i = 0; i < XMSS_OID_LEN; i++) { | for (i = 0; i < XMSS_OID_LEN; i++) { | ||||
oid |= pk[i] << (i * 8); | oid |= pk[i] << (i * 8); | ||||
} | } | ||||
if (xmss_parse_oid(oid)) { | |||||
if (xmss_parse_oid(¶ms, oid)) { | |||||
return 1; | 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) | int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) | ||||
{ | { | ||||
xmss_params params; | |||||
unsigned int i; | unsigned int i; | ||||
if (xmssmt_parse_oid(oid)) { | |||||
if (xmssmt_parse_oid(¶ms, oid)) { | |||||
return 1; | return 1; | ||||
} | } | ||||
for (i = 0; i < XMSS_OID_LEN; i++) { | for (i = 0; i < XMSS_OID_LEN; i++) { | ||||
pk[i] = (oid >> (8 * i)) & 0xFF; | pk[i] = (oid >> (8 * i)) & 0xFF; | ||||
sk[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, | int xmssmt_sign(unsigned char *sk, | ||||
unsigned char *sm, unsigned long long *smlen, | unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen) | const unsigned char *m, unsigned long long mlen) | ||||
{ | { | ||||
xmss_params params; | |||||
uint32_t oid = 0; | uint32_t oid = 0; | ||||
unsigned int i; | unsigned int i; | ||||
for (i = 0; i < XMSS_OID_LEN; i++) { | for (i = 0; i < XMSS_OID_LEN; i++) { | ||||
oid |= sk[i] << (i * 8); | oid |= sk[i] << (i * 8); | ||||
} | } | ||||
if (xmssmt_parse_oid(oid)) { | |||||
if (xmssmt_parse_oid(¶ms, oid)) { | |||||
return 1; | 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, | int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen, | ||||
const unsigned char *sm, unsigned long long smlen, | const unsigned char *sm, unsigned long long smlen, | ||||
const unsigned char *pk) | const unsigned char *pk) | ||||
{ | { | ||||
xmss_params params; | |||||
uint32_t oid = 0; | uint32_t oid = 0; | ||||
unsigned int i; | unsigned int i; | ||||
for (i = 0; i < XMSS_OID_LEN; i++) { | for (i = 0; i < XMSS_OID_LEN; i++) { | ||||
oid |= pk[i] << (i * 8); | oid |= pk[i] << (i * 8); | ||||
} | } | ||||
if (xmssmt_parse_oid(oid)) { | |||||
if (xmssmt_parse_oid(¶ms, oid)) { | |||||
return 1; | 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); | |||||
} | } |
@@ -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. | * 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, | const unsigned char *sk_seed, const unsigned char *pub_seed, | ||||
uint32_t ltree_addr[8], uint32_t ots_addr[8]) | 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, | * Used for pseudorandom keygeneration, | ||||
* generates the seed for the WOTS keypair at address addr | * generates the seed for the WOTS keypair at address addr | ||||
* | * | ||||
* takes 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]) | const unsigned char *sk_seed, uint32_t addr[8]) | ||||
{ | { | ||||
unsigned char bytes[32]; | unsigned char bytes[32]; | ||||
@@ -58,16 +58,16 @@ void get_seed(unsigned char *seed, | |||||
set_key_and_mask(addr, 0); | set_key_and_mask(addr, 0); | ||||
// Generate pseudorandom value | // Generate pseudorandom value | ||||
addr_to_byte(bytes, addr); | 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. | * 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]) | 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 i = 0; | ||||
uint32_t height = 0; | uint32_t height = 0; | ||||
uint32_t bound; | uint32_t bound; | ||||
@@ -78,10 +78,10 @@ void l_tree(unsigned char *leaf, unsigned char *wots_pk, | |||||
bound = l >> 1; | bound = l >> 1; | ||||
for (i = 0; i < bound; i++) { | for (i = 0; i < bound; i++) { | ||||
set_tree_index(addr, 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) { | 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; | l = (l >> 1) + 1; | ||||
} | } | ||||
else { | else { | ||||
@@ -90,77 +90,78 @@ void l_tree(unsigned char *leaf, unsigned char *wots_pk, | |||||
height++; | height++; | ||||
set_tree_height(addr, 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 | * 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 *leaf, unsigned long leafidx, | ||||
const unsigned char *authpath, | const unsigned char *authpath, | ||||
const unsigned char *pub_seed, uint32_t addr[8]) | const unsigned char *pub_seed, uint32_t addr[8]) | ||||
{ | { | ||||
uint32_t i, j; | 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. | // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. | ||||
// Otherwise, it is the other way around | // Otherwise, it is the other way around | ||||
if (leafidx & 1) { | if (leafidx & 1) { | ||||
for (j = 0; j < 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]; | buffer[j] = authpath[j]; | ||||
} | } | ||||
} | } | ||||
else { | else { | ||||
for (j = 0; j < XMSS_N; j++) { | |||||
for (j = 0; j < params->n; j++) { | |||||
buffer[j] = leaf[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); | set_tree_height(addr, i); | ||||
leafidx >>= 1; | leafidx >>= 1; | ||||
set_tree_index(addr, leafidx); | set_tree_index(addr, leafidx); | ||||
if (leafidx & 1) { | 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]; | buffer[j] = authpath[j]; | ||||
} | } | ||||
} | } | ||||
else { | 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; | leafidx >>= 1; | ||||
set_tree_index(addr, leafidx); | 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. | * 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 *sm, unsigned long long smlen, | ||||
const unsigned char *pk) | const unsigned char *pk) | ||||
{ | { | ||||
unsigned long long i; | unsigned long long i; | ||||
unsigned long idx = 0; | 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 | // Init addresses | ||||
uint32_t ots_addr[8] = {0}; | 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(ltree_addr, 1); | ||||
set_type(node_addr, 2); | set_type(node_addr, 2); | ||||
*mlen = smlen - XMSS_BYTES; | |||||
*mlen = smlen - params->bytes; | |||||
// Extract index | // 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) | // 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 | // 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 | // Prepare Address | ||||
set_ots_addr(ots_addr, idx); | set_ots_addr(ots_addr, idx); | ||||
// Check WOTS signature | // 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 | // Compute Ltree | ||||
set_ltree_addr(ltree_addr, idx); | 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 | // 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]) { | if (root[i] != pk[i]) { | ||||
for (i = 0; i < *mlen; i++) { | for (i = 0; i < *mlen; i++) { | ||||
m[i] = 0; | 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. | * 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 *sm, unsigned long long smlen, | ||||
const unsigned char *pk) | const unsigned char *pk) | ||||
{ | { | ||||
uint32_t idx_leaf; | uint32_t idx_leaf; | ||||
unsigned long long i; | unsigned long long i; | ||||
unsigned long long idx = 0; | 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 *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 | // Init addresses | ||||
uint32_t ots_addr[8] = {0}; | 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(ltree_addr, 1); | ||||
set_type(node_addr, 2); | set_type(node_addr, 2); | ||||
*mlen = smlen - XMSS_BYTES; | |||||
*mlen = smlen - params->bytes; | |||||
// Extract index | // 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) | // 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 | // 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 | // 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(ots_addr, i); | ||||
set_layer_addr(ltree_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); | set_ots_addr(ots_addr, idx_leaf); | ||||
// Check WOTS signature | // 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 | // Compute Ltree | ||||
set_ltree_addr(ltree_addr, idx_leaf); | 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 | // 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]) { | if (root[i] != pk[i]) { | ||||
for (i = 0; i < *mlen; i++) { | for (i = 0; i < *mlen; i++) { | ||||
m[i] = 0; | m[i] = 0; | ||||
@@ -9,26 +9,29 @@ Public domain. | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include "params.h" | |||||
void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); | void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); | ||||
void hexdump(const unsigned char *a, size_t len); | 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, | const unsigned char *sk_seed, const unsigned char *pub_seed, | ||||
uint32_t ltree_addr[8], uint32_t ots_addr[8]); | 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]); | 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]); | 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 *sm, unsigned long long smlen, | ||||
const unsigned char *pk); | 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 *sm, unsigned long long smlen, | ||||
const unsigned char *pk); | const unsigned char *pk); | ||||
#endif | #endif |
@@ -22,7 +22,7 @@ Public domain. | |||||
* Currently only used for key generation. | * 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; | uint32_t idx = index; | ||||
// use three different addresses because at this point we use all three formats in parallel | // use three different addresses because at this point we use all three formats in parallel | ||||
@@ -39,27 +39,27 @@ static void treehash(unsigned char *node, uint32_t index, const unsigned char *s | |||||
set_type(node_addr, 2); | set_type(node_addr, 2); | ||||
uint32_t lastnode, i; | 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; | unsigned int stackoffset=0; | ||||
lastnode = idx+(1 << XMSS_TREEHEIGHT); | |||||
lastnode = idx+(1 << params->tree_height); | |||||
for (; idx < lastnode; idx++) { | for (; idx < lastnode; idx++) { | ||||
set_ltree_addr(ltree_addr, idx); | set_ltree_addr(ltree_addr, idx); | ||||
set_ots_addr(ots_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; | stacklevels[stackoffset] = 0; | ||||
stackoffset++; | stackoffset++; | ||||
while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { | while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { | ||||
set_tree_height(node_addr, stacklevels[stackoffset-1]); | set_tree_height(node_addr, stacklevels[stackoffset-1]); | ||||
set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+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]++; | stacklevels[stackoffset-2]++; | ||||
stackoffset--; | stackoffset--; | ||||
} | } | ||||
} | } | ||||
for (i = 0; i < XMSS_N; i++) { | |||||
for (i = 0; i < params->n; i++) { | |||||
node[i] = stack[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. | * For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009. | ||||
* It returns the authpath in "authpath" with the node on level 0 at index 0. | * It returns the authpath in "authpath" with the node on level 0 at index 0. | ||||
*/ | */ | ||||
static void compute_authpath_wots(unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, 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; | uint32_t i, j, level; | ||||
unsigned char tree[2*(1<<XMSS_TREEHEIGHT)*XMSS_N]; | |||||
unsigned char tree[2*(1 << params->tree_height)*params->n]; | |||||
uint32_t ots_addr[8]; | uint32_t ots_addr[8]; | ||||
uint32_t ltree_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); | set_type(node_addr, 2); | ||||
// Compute all leaves | // 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_ltree_addr(ltree_addr, i); | ||||
set_ots_addr(ots_addr, i); | set_ots_addr(ots_addr, i); | ||||
gen_leaf_wots(tree+((1<<XMSS_TREEHEIGHT)*XMSS_N + i*XMSS_N), sk_seed, pub_seed, ltree_addr, ots_addr); | |||||
gen_leaf_wots(params, tree+((1 << params->tree_height)*params->n + i*params->n), sk_seed, pub_seed, ltree_addr, ots_addr); | |||||
} | } | ||||
level = 0; | level = 0; | ||||
// Compute tree: | // Compute tree: | ||||
// Outer loop: For each inner layer | // Outer loop: For each inner layer | ||||
for (i = (1<<XMSS_TREEHEIGHT); i > 1; i>>=1) { | |||||
for (i = (1 << params->tree_height); i > 1; i>>=1) { | |||||
set_tree_height(node_addr, level); | set_tree_height(node_addr, level); | ||||
// Inner loop: for each pair of sibling nodes | // Inner loop: for each pair of sibling nodes | ||||
for (j = 0; j < i; j+=2) { | for (j = 0; j < i; j+=2) { | ||||
set_tree_index(node_addr, j>>1); | 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++; | level++; | ||||
} | } | ||||
// copy authpath | // copy authpath | ||||
for (i = 0; i < XMSS_TREEHEIGHT; i++) { | |||||
memcpy(authpath + i*XMSS_N, tree + ((1<<XMSS_TREEHEIGHT)>>i)*XMSS_N + ((leaf_idx >> i) ^ 1) * XMSS_N, XMSS_N); | |||||
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 | // 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 sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_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 | // Set idx = 0 | ||||
sk[0] = 0; | sk[0] = 0; | ||||
sk[1] = 0; | sk[1] = 0; | ||||
sk[2] = 0; | sk[2] = 0; | ||||
sk[3] = 0; | sk[3] = 0; | ||||
// Init SK_SEED (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 | // 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}; | uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
// Compute root | // 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 | // copy root to sk | ||||
memcpy(sk+4+3*XMSS_N, pk, XMSS_N); | |||||
memcpy(sk+4+3*params->n, pk, params->n); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -149,24 +149,24 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk) | |||||
* 2. an updated secret key! | * 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; | uint16_t i = 0; | ||||
// Extract SK | // Extract SK | ||||
uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | ||||
unsigned char sk_seed[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 | // index as 32 bytes string | ||||
unsigned char idx_bytes_32[32]; | unsigned char idx_bytes_32[32]; | ||||
to_byte(idx_bytes_32, idx, 32); | to_byte(idx_bytes_32, idx, 32); | ||||
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 | // Update SK | ||||
sk[0] = ((idx + 1) >> 24) & 255; | 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! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
// Init working params | // Init working params | ||||
unsigned char R[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}; | 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: | // Message Hash: | ||||
// First compute pseudorandom value | // 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) | // 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 | // 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 | // Start collecting signature | ||||
*smlen = 0; | *smlen = 0; | ||||
@@ -210,11 +210,11 @@ int xmss_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *sml | |||||
*smlen += 4; | *smlen += 4; | ||||
// Copy R to signature | // Copy R to signature | ||||
for (i = 0; i < XMSS_N; i++) | |||||
for (i = 0; i < params->n; i++) | |||||
sm[i] = R[i]; | sm[i] = R[i]; | ||||
sm += XMSS_N; | |||||
*smlen += XMSS_N; | |||||
sm += params->n; | |||||
*smlen += params->n; | |||||
// ---------------------------------- | // ---------------------------------- | ||||
// Now we start to "really sign" | // 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); | set_ots_addr(ots_addr, idx); | ||||
// Compute seed for OTS key pair | // 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 | // 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); | memcpy(sm, m, mlen); | ||||
*smlen += 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 sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_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; | uint16_t i; | ||||
// Set idx = 0 | // Set idx = 0 | ||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
for (i = 0; i < params->index_len; i++) { | |||||
sk[i] = 0; | 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 | // 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 | // Set address to point on the single tree on layer d-1 | ||||
uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
set_layer_addr(addr, (XMSS_D-1)); | |||||
set_layer_addr(addr, (params->d-1)); | |||||
// Compute root | // 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; | return 0; | ||||
} | } | ||||
@@ -277,37 +277,37 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk) | |||||
* 2. an updated secret key! | * 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; | uint64_t idx_tree; | ||||
uint32_t idx_leaf; | uint32_t idx_leaf; | ||||
uint64_t i; | 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 | // 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}; | uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
unsigned char idx_bytes_32[32]; | unsigned char idx_bytes_32[32]; | ||||
// Extract SK | // Extract SK | ||||
unsigned long long idx = 0; | unsigned long long idx = 0; | ||||
for (i = 0; i < 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 | // 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. | // -- Secret key for this non-forward-secure version is now updated. | ||||
// -- A productive implementation should use a file handle instead and write the updated secret key at this point! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
@@ -320,33 +320,33 @@ int xmssmt_core_sign(unsigned char *sk, unsigned char *sm, unsigned long long *s | |||||
// Message Hash: | // Message Hash: | ||||
// First compute pseudorandom value | // First compute pseudorandom value | ||||
to_byte(idx_bytes_32, idx, 32); | to_byte(idx_bytes_32, idx, 32); | ||||
prf(R, idx_bytes_32, sk_prf, XMSS_N); | |||||
prf(params, R, idx_bytes_32, sk_prf, params->n); | |||||
// Generate hash key (R || root || idx) | // 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 | // 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 | // Start collecting signature | ||||
*smlen = 0; | *smlen = 0; | ||||
// Copy index to signature | // 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 | // Copy R to signature | ||||
for (i = 0; i < XMSS_N; i++) { | |||||
for (i = 0; i < params->n; i++) { | |||||
sm[i] = R[i]; | sm[i] = R[i]; | ||||
} | } | ||||
sm += XMSS_N; | |||||
*smlen += XMSS_N; | |||||
sm += params->n; | |||||
*smlen += params->n; | |||||
// ---------------------------------- | // ---------------------------------- | ||||
// Now we start to "really sign" | // 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 | // Prepare Address | ||||
set_type(ots_addr, 0); | 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_layer_addr(ots_addr, 0); | ||||
set_tree_addr(ots_addr, idx_tree); | set_tree_addr(ots_addr, idx_tree); | ||||
set_ots_addr(ots_addr, idx_leaf); | set_ots_addr(ots_addr, idx_leaf); | ||||
// Compute seed for OTS key pair | // 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 | // 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... | // Now loop over remaining layers... | ||||
unsigned int j; | unsigned int j; | ||||
for (j = 1; j < XMSS_D; j++) { | |||||
for (j = 1; j < params->d; j++) { | |||||
// Prepare Address | // 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_layer_addr(ots_addr, j); | ||||
set_tree_addr(ots_addr, idx_tree); | set_tree_addr(ots_addr, idx_tree); | ||||
set_ots_addr(ots_addr, idx_leaf); | set_ots_addr(ots_addr, idx_leaf); | ||||
// Compute seed for OTS key pair | // 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 | // 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); | memcpy(sm, m, mlen); | ||||
@@ -15,7 +15,7 @@ Public domain. | |||||
* Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_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. | * Signs a message. | ||||
* Returns | * Returns | ||||
@@ -23,20 +23,20 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk); | |||||
* 2. an updated secret key! | * 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. | * Verifies a given message signature pair under a given public key. | ||||
* | * | ||||
* Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). | * Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). | ||||
*/ | */ | ||||
int xmss_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. | * Generates a XMSSMT key pair for a given parameter set. | ||||
* Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_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. | * Signs a message. | ||||
* Returns | * Returns | ||||
@@ -44,10 +44,10 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk); | |||||
* 2. an updated secret key! | * 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. | * 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 | #endif | ||||
@@ -37,10 +37,11 @@ void xmss_set_bds_state(bds_state *state, unsigned char *stack, | |||||
state->next_leaf = next_leaf; | 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) | const treehash_inst *treehash) | ||||
{ | { | ||||
unsigned int r = XMSS_TREEHEIGHT, i; | |||||
unsigned int r = params->tree_height, i; | |||||
for (i = 0; i < treehash->stackusage; i++) { | for (i = 0; i < treehash->stackusage; i++) { | ||||
if (state->stacklevels[state->stackoffset - i - 1] < r) { | 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. | * 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, | bds_state *state, const unsigned char *sk_seed, | ||||
const unsigned char *pub_seed, const uint32_t addr[8]) | 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); | set_type(node_addr, 2); | ||||
uint32_t lastnode, i; | 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 stacklevels[height+1]; | ||||
unsigned int stackoffset=0; | unsigned int stackoffset=0; | ||||
unsigned int nodeh; | unsigned int nodeh; | ||||
lastnode = idx+(1<<height); | lastnode = idx+(1<<height); | ||||
for (i = 0; i < XMSS_TREEHEIGHT-XMSS_BDS_K; i++) { | |||||
for (i = 0; i < params->tree_height-params->bds_k; i++) { | |||||
state->treehash[i].h = i; | state->treehash[i].h = i; | ||||
state->treehash[i].completed = 1; | state->treehash[i].completed = 1; | ||||
state->treehash[i].stackusage = 0; | state->treehash[i].stackusage = 0; | ||||
@@ -91,40 +93,41 @@ static void treehash_init(unsigned char *node, int height, int index, | |||||
for (; idx < lastnode; idx++) { | for (; idx < lastnode; idx++) { | ||||
set_ltree_addr(ltree_addr, idx); | set_ltree_addr(ltree_addr, idx); | ||||
set_ots_addr(ots_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; | stacklevels[stackoffset] = 0; | ||||
stackoffset++; | 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]) { | while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) { | ||||
nodeh = stacklevels[stackoffset-1]; | nodeh = stacklevels[stackoffset-1]; | ||||
if (i >> nodeh == 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 { | 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_height(node_addr, stacklevels[stackoffset-1]); | ||||
set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+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]++; | stacklevels[stackoffset-2]++; | ||||
stackoffset--; | stackoffset--; | ||||
} | } | ||||
i++; | i++; | ||||
} | } | ||||
for (i = 0; i < XMSS_N; i++) { | |||||
for (i = 0; i < params->n; i++) { | |||||
node[i] = stack[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 *sk_seed, | ||||
const unsigned char *pub_seed, | const unsigned char *pub_seed, | ||||
const uint32_t addr[8]) | 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_ltree_addr(ltree_addr, treehash->next_idx); | ||||
set_ots_addr(ots_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; | 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) { | 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_height(node_addr, nodeheight); | ||||
set_tree_index(node_addr, (treehash->next_idx >> (nodeheight+1))); | 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++; | nodeheight++; | ||||
treehash->stackusage--; | treehash->stackusage--; | ||||
state->stackoffset--; | state->stackoffset--; | ||||
} | } | ||||
if (nodeheight == treehash->h) { // this also implies stackusage == 0 | if (nodeheight == treehash->h) { // this also implies stackusage == 0 | ||||
memcpy(treehash->node, nodebuffer, XMSS_N); | |||||
memcpy(treehash->node, nodebuffer, params->n); | |||||
treehash->completed = 1; | treehash->completed = 1; | ||||
} | } | ||||
else { | else { | ||||
memcpy(state->stack + state->stackoffset*XMSS_N, nodebuffer, XMSS_N); | |||||
memcpy(state->stack + state->stackoffset*params->n, nodebuffer, params->n); | |||||
treehash->stackusage++; | treehash->stackusage++; | ||||
state->stacklevels[state->stackoffset] = nodeheight; | state->stacklevels[state->stackoffset] = nodeheight; | ||||
state->stackoffset++; | 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. | * Performs one treehash update on the instance that needs it the most. | ||||
* Returns 1 if such an instance was not found | * 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, | const unsigned char *sk_seed, | ||||
unsigned char *pub_seed, | unsigned char *pub_seed, | ||||
const uint32_t addr[8]) | const uint32_t addr[8]) | ||||
@@ -184,27 +188,27 @@ static char bds_treehash_update(bds_state *state, unsigned int updates, | |||||
unsigned int used = 0; | unsigned int used = 0; | ||||
for (j = 0; j < updates; j++) { | 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) { | if (state->treehash[i].completed) { | ||||
low = XMSS_TREEHEIGHT; | |||||
low = params->tree_height; | |||||
} | } | ||||
else if (state->treehash[i].stackusage == 0) { | else if (state->treehash[i].stackusage == 0) { | ||||
low = i; | low = i; | ||||
} | } | ||||
else { | else { | ||||
low = treehash_minheight_on_stack(state, &(state->treehash[i])); | |||||
low = treehash_minheight_on_stack(params, state, &(state->treehash[i])); | |||||
} | } | ||||
if (low < l_min) { | if (low < l_min) { | ||||
level = i; | level = i; | ||||
l_min = low; | l_min = low; | ||||
} | } | ||||
} | } | ||||
if (level == XMSS_TREEHEIGHT - XMSS_BDS_K) { | |||||
if (level == params->tree_height - params->bds_k) { | |||||
break; | 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++; | used++; | ||||
} | } | ||||
return updates - 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 | * Updates the state (typically NEXT_i) by adding a leaf and updating the stack | ||||
* Returns 1 if all leaf nodes have already been processed | * 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 unsigned char *pub_seed, | ||||
const uint32_t addr[8]) | 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 nodeh; | ||||
int idx = state->next_leaf; | int idx = state->next_leaf; | ||||
if (idx == 1 << XMSS_TREEHEIGHT) { | |||||
if (idx == 1 << params->tree_height) { | |||||
return 1; | 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_ots_addr(ots_addr, idx); | ||||
set_ltree_addr(ltree_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->stacklevels[state->stackoffset] = 0; | ||||
state->stackoffset++; | 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]) { | while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) { | ||||
nodeh = state->stacklevels[state->stackoffset-1]; | nodeh = state->stacklevels[state->stackoffset-1]; | ||||
if (idx >> nodeh == 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 { | 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_height(node_addr, state->stacklevels[state->stackoffset-1]); | ||||
set_tree_index(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+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->stacklevels[state->stackoffset-2]++; | ||||
state->stackoffset--; | 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 | * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo | ||||
* in "Post Quantum Cryptography", Springer 2009. | * 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 *sk_seed, | ||||
const unsigned char *pub_seed, uint32_t addr[8]) | const unsigned char *pub_seed, uint32_t addr[8]) | ||||
{ | { | ||||
unsigned int i; | unsigned int i; | ||||
unsigned int tau = XMSS_TREEHEIGHT; | |||||
unsigned int tau = params->tree_height; | |||||
unsigned int startidx; | unsigned int startidx; | ||||
unsigned int offset, rowidx; | unsigned int offset, rowidx; | ||||
unsigned char buf[2 * XMSS_N]; | |||||
unsigned char buf[2 * params->n]; | |||||
uint32_t ots_addr[8]; | uint32_t ots_addr[8]; | ||||
uint32_t ltree_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); | memcpy(node_addr, addr, 12); | ||||
set_type(node_addr, 2); | 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)) { | if (! ((leaf_idx >> i) & 1)) { | ||||
tau = i; | tau = i; | ||||
break; | break; | ||||
@@ -306,36 +312,36 @@ static void bds_round(bds_state *state, const unsigned long leaf_idx, | |||||
} | } | ||||
if (tau > 0) { | 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 | // 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) { | if (tau == 0) { | ||||
set_ltree_addr(ltree_addr, leaf_idx); | set_ltree_addr(ltree_addr, leaf_idx); | ||||
set_ots_addr(ots_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 { | else { | ||||
set_tree_height(node_addr, (tau-1)); | set_tree_height(node_addr, (tau-1)); | ||||
set_tree_index(node_addr, leaf_idx >> tau); | 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++) { | 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 { | 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; | 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); | 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].h = i; | ||||
state->treehash[i].next_idx = startidx; | state->treehash[i].next_idx = startidx; | ||||
state->treehash[i].completed = 0; | 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 sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_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}; | 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[2] = 0; | ||||
sk[3] = 0; | sk[3] = 0; | ||||
// Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) | // 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 | // 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 | // 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 | // 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; | return 0; | ||||
} | } | ||||
@@ -378,7 +385,8 @@ int xmss_core_keypair(unsigned char *pk, unsigned char *sk, bds_state *state) | |||||
* 2. an updated secret key! | * 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, | unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen) | const unsigned char *m, unsigned long long mlen) | ||||
{ | { | ||||
@@ -386,18 +394,18 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, | |||||
// Extract SK | // Extract SK | ||||
unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; | 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 | // index as 32 bytes string | ||||
unsigned char idx_bytes_32[32]; | unsigned char idx_bytes_32[32]; | ||||
to_byte(idx_bytes_32, idx, 32); | to_byte(idx_bytes_32, idx, 32); | ||||
unsigned char hash_key[3*XMSS_N]; | |||||
unsigned char hash_key[3*params->n]; | |||||
// Update SK | // Update SK | ||||
sk[0] = ((idx + 1) >> 24) & 255; | 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! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
// Init working params | // Init working params | ||||
unsigned char R[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}; | 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: | // Message Hash: | ||||
// First compute pseudorandom value | // 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) | // 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 | // 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 | // Start collecting signature | ||||
*smlen = 0; | *smlen = 0; | ||||
@@ -440,12 +448,12 @@ int xmss_core_sign(unsigned char *sk, bds_state *state, | |||||
*smlen += 4; | *smlen += 4; | ||||
// Copy R to signature | // Copy R to signature | ||||
for (i = 0; i < XMSS_N; i++) { | |||||
for (i = 0; i < params->n; i++) { | |||||
sm[i] = R[i]; | sm[i] = R[i]; | ||||
} | } | ||||
sm += XMSS_N; | |||||
*smlen += XMSS_N; | |||||
sm += params->n; | |||||
*smlen += params->n; | |||||
// ---------------------------------- | // ---------------------------------- | ||||
// Now we start to "really sign" | // 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); | set_ots_addr(ots_addr, idx); | ||||
// Compute seed for OTS key pair | // 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 | // 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 | // 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); | memcpy(sm, m, mlen); | ||||
*smlen += 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 sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_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) | 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}; | uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
int i; | int i; | ||||
// Set idx = 0 | // Set idx = 0 | ||||
for (i = 0; i < XMSS_INDEX_LEN; i++) { | |||||
for (i = 0; i < params->index_len; i++) { | |||||
sk[i] = 0; | 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 | // 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 | // Start with the bottom-most layer | ||||
set_layer_addr(addr, 0); | set_layer_addr(addr, 0); | ||||
// Set up state and compute wots signatures for all but topmost tree root | // 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 | // 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)); | 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 | // 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; | return 0; | ||||
} | } | ||||
@@ -525,7 +534,8 @@ int xmssmt_core_keypair(unsigned char *pk, unsigned char *sk, | |||||
* 2. an updated secret key! | * 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, | bds_state *states, unsigned char *wots_sigs, | ||||
unsigned char *sm, unsigned long long *smlen, | unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen) | const unsigned char *m, unsigned long long mlen) | ||||
@@ -536,14 +546,14 @@ int xmssmt_core_sign(unsigned char *sk, | |||||
int needswap_upto = -1; | int needswap_upto = -1; | ||||
unsigned int updates; | 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 | // 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 addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
unsigned char idx_bytes_32[32]; | unsigned char idx_bytes_32[32]; | ||||
@@ -551,17 +561,17 @@ int xmssmt_core_sign(unsigned char *sk, | |||||
// Extract SK | // Extract SK | ||||
unsigned long long idx = 0; | 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 | // 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. | // -- Secret key for this non-forward-secure version is now updated. | ||||
// -- A productive implementation should use a file handle instead and write the updated secret key at this point! | // -- A productive implementation should use a file handle instead and write the updated secret key at this point! | ||||
@@ -574,33 +584,33 @@ int xmssmt_core_sign(unsigned char *sk, | |||||
// Message Hash: | // Message Hash: | ||||
// First compute pseudorandom value | // First compute pseudorandom value | ||||
to_byte(idx_bytes_32, idx, 32); | to_byte(idx_bytes_32, idx, 32); | ||||
prf(R, idx_bytes_32, sk_prf, XMSS_N); | |||||
prf(params, R, idx_bytes_32, sk_prf, params->n); | |||||
// Generate hash key (R || root || idx) | // 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 | // 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 | // Start collecting signature | ||||
*smlen = 0; | *smlen = 0; | ||||
// Copy index to signature | // 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 | // Copy R to signature | ||||
for (i = 0; i < XMSS_N; i++) { | |||||
for (i = 0; i < params->n; i++) { | |||||
sm[i] = R[i]; | sm[i] = R[i]; | ||||
} | } | ||||
sm += XMSS_N; | |||||
*smlen += XMSS_N; | |||||
sm += params->n; | |||||
*smlen += params->n; | |||||
// ---------------------------------- | // ---------------------------------- | ||||
// Now we start to "really sign" | // Now we start to "really sign" | ||||
@@ -610,85 +620,85 @@ int xmssmt_core_sign(unsigned char *sk, | |||||
// Prepare Address | // Prepare Address | ||||
set_type(ots_addr, 0); | 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_layer_addr(ots_addr, 0); | ||||
set_tree_addr(ots_addr, idx_tree); | set_tree_addr(ots_addr, idx_tree); | ||||
set_ots_addr(ots_addr, idx_leaf); | set_ots_addr(ots_addr, idx_leaf); | ||||
// Compute seed for OTS key pair | // 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 | // 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 | // prepare signature of remaining layers | ||||
for (i = 1; i < XMSS_D; i++) { | |||||
for (i = 1; i < params->d; i++) { | |||||
// put WOTS signature in place | // 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 | // 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)); | set_tree_addr(addr, (idx_tree + 1)); | ||||
// mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists | // 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 | // 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_layer_addr(addr, i); | ||||
set_tree_addr(addr, idx_tree); | set_tree_addr(addr, idx_tree); | ||||
if (i == (unsigned int) (needswap_upto + 1)) { | 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)); | set_tree_addr(addr, (idx_tree + 1)); | ||||
// if a NEXT-tree exists for this level; | // 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--; | 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)); | memcpy(states + i, &tmp, sizeof(bds_state)); | ||||
set_layer_addr(ots_addr, (i+1)); | 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 | updates--; // WOTS-signing counts as one update | ||||
needswap_upto = i; | 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; | states[i].treehash[j].completed = 1; | ||||
} | } | ||||
} | } | ||||
@@ -8,6 +8,8 @@ Public domain. | |||||
#ifndef XMSS_CORE_H | #ifndef XMSS_CORE_H | ||||
#define XMSS_CORE_H | #define XMSS_CORE_H | ||||
#include "params.h" | |||||
typedef struct{ | typedef struct{ | ||||
unsigned int h; | unsigned int h; | ||||
unsigned int next_idx; | 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 sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmss_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. | * Signs a message. | ||||
* Returns | * Returns | ||||
* 1. an array containing the signature followed by the message AND | * 1. an array containing the signature followed by the message AND | ||||
* 2. an updated secret key! | * 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, | unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen); | 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). | * 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 *sm, unsigned long long smlen, | ||||
const unsigned char *pk); | 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 sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] | ||||
* Format pk: [root || PUB_SEED] omitting algo oid. | * Format pk: [root || PUB_SEED] omitting algo oid. | ||||
*/ | */ | ||||
int xmssmt_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); | 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 | * 1. an array containing the signature followed by the message AND | ||||
* 2. an updated secret key! | * 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, | bds_state *states, unsigned char *wots_sigs, | ||||
unsigned char *sm, unsigned long long *smlen, | unsigned char *sm, unsigned long long *smlen, | ||||
const unsigned char *m, unsigned long long mlen); | 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. | * 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 *sm, unsigned long long smlen, | ||||
const unsigned char *pk); | const unsigned char *pk); | ||||
#endif | #endif |