diff --git a/pq/stateful_hash_sig/0001-Patch-to-support-xmss-reference-integration.patch b/pq/stateful_hash_sig/0001-Patch-to-support-wolfSSL-xmss-reference-integration.patch similarity index 58% rename from pq/stateful_hash_sig/0001-Patch-to-support-xmss-reference-integration.patch rename to pq/stateful_hash_sig/0001-Patch-to-support-wolfSSL-xmss-reference-integration.patch index 3d0dd217..975561d9 100644 --- a/pq/stateful_hash_sig/0001-Patch-to-support-xmss-reference-integration.patch +++ b/pq/stateful_hash_sig/0001-Patch-to-support-wolfSSL-xmss-reference-integration.patch @@ -1,38 +1,90 @@ -From 14b855cbad45bd19ee3e9e591cc6b426f8b5c9da Mon Sep 17 00:00:00 2001 +From 605ac49e4c4bcb65191c1c9bb821cbc31354e1e3 Mon Sep 17 00:00:00 2001 From: jordan -Date: Thu, 5 Oct 2023 08:39:19 -0500 -Subject: [PATCH 1/1] Patch to support xmss-reference integration with - wolfCrypt and wolfBoot. +Date: Mon, 9 Oct 2023 11:31:08 -0500 +Subject: [PATCH 1/1] Patch to support wolfSSL xmss-reference integration. --- - Makefile | 2 + - fips202.c | 2 +- - hash_address.c | 2 + - params.h | 15 +++ - hash.c => thash.c | 110 ++++++++++++++++++++-- - hash.h => thash.h | 0 - wots.c | 35 ++++++- - xmss.c | 53 ++++++----- - xmss.h | 36 ++++---- - xmss_commons.c | 77 ++++++++++------ - xmss_commons.h | 4 +- - xmss_core.c | 34 ++++--- - xmss_core.h | 26 +++--- - xmss_core_fast.c | 230 ++++++++++++++++++++++++++++++---------------- - 14 files changed, 443 insertions(+), 183 deletions(-) - rename hash.c => thash.c (68%) - rename hash.h => thash.h (100%) + Makefile | 36 +++++- + fips202.c | 2 +- + hash_address.c | 2 + + params.h | 15 +++ + randombytes.c | 2 + + test/speed.c | 98 +++++++++++++-- + test/wots.c | 77 ++++++++++++ + test/xmss.c | 135 +++++++++++++++------ + test/xmss_determinism.c | 77 ++++++++++++ + test/xmss_max_signatures.c | 72 +++++++++++ + hash.c => thash.c | 72 +++++++++-- + hash.h => thash.h | 5 +- + ui/keypair.c | 73 ++++++++++++ + wots.c | 31 ++++- + xmss.c | 41 ++++--- + xmss.h | 30 ++--- + xmss_callbacks.h | 12 ++ + xmss_commons.c | 77 ++++++++---- + xmss_commons.h | 4 +- + xmss_core.c | 60 ++++++++-- + xmss_core.h | 22 ++-- + xmss_core_fast.c | 238 +++++++++++++++++++++++++------------ + 22 files changed, 957 insertions(+), 224 deletions(-) + rename hash.c => thash.c (79%) + rename hash.h => thash.h (96%) + create mode 100644 xmss_callbacks.h diff --git a/Makefile b/Makefile -index d1b95d5..435c854 100644 +index d1b95d5..599df68 100644 --- a/Makefile +++ b/Makefile -@@ -87,3 +87,5 @@ clean: +@@ -1,9 +1,10 @@ + CC = /usr/bin/gcc +-CFLAGS = -Wall -g -O3 -Wextra -Wpedantic +-LDLIBS = -lcrypto ++CFLAGS = -Wall -O2 -Wextra -Wpedantic ++VERIFY_CFLAGS = -DXMSS_VERIFY_ONLY -Wall -O2 -Wextra -Wpedantic ++LDLIBS = -lwolfssl + +-SOURCES = params.c hash.c fips202.c hash_address.c randombytes.c wots.c xmss.c xmss_core.c xmss_commons.c utils.c +-HEADERS = params.h hash.h fips202.h hash_address.h randombytes.h wots.h xmss.h xmss_core.h xmss_commons.h utils.h ++SOURCES = params.c thash.c fips202.c hash_address.c randombytes.c wots.c xmss.c xmss_core.c xmss_commons.c utils.c ++HEADERS = params.h thash.h fips202.h hash_address.h randombytes.h wots.h xmss.h xmss_core.h xmss_commons.h utils.h + + SOURCES_FAST = $(subst xmss_core.c,xmss_core_fast.c,$(SOURCES)) + HEADERS_FAST = $(subst xmss_core.c,xmss_core_fast.c,$(HEADERS)) +@@ -83,7 +84,34 @@ ui/xmss_%: ui/%.c $(SOURCES) $(OBJS) $(HEADERS) + ui/xmssmt_%: ui/%.c $(SOURCES) $(OBJS) $(HEADERS) + $(CC) -DXMSSMT $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) + ++# Only the test xmss executables link with wolfssl. ++# xmss_lib.a does not link with wolfssl, as this would create circular ++# dependencies. ++xmss_lib.a: params.o thash.o hash_address.o wots.o xmss.o xmss_core_fast.o \ ++ xmss_commons.o utils.o ++ $(AR) rcs $@ $^ ++ ++xmss_verify_lib.a: CFLAGS += -DXMSS_VERIFY_ONLY ++ ++xmss_verify_lib.a: params.o thash.o hash_address.o wots.o xmss.o xmss_core_fast.o \ ++ xmss_commons.o utils.o ++ $(AR) rcs $@ $^ ++ + clean: -$(RM) $(TESTS) -$(RM) test/vectors -$(RM) $(UI) + -$(RM) *.o + -$(RM) *.lo ++ -$(RM) xmss_lib.a ++ ++#%.o:%.c ++# @echo "[$(CC)] $@" ++# $(CC) -DXMSSMT -fPIC $(CFLAGS) -c -o $@ $< ++ ++#wolfcrypt_integration: params.lo thash.lo hash_address.lo wots.lo xmss.lo xmss_core_fast.lo xmss_commons.lo utils.lo ++# ++#%.lo:%.c ++# @echo "[$(CC)] $@" ++## $(CC) -fPIC $(CFLAGS) -c -o $@ $< ++# libtool --tag=CC --mode=compile $(CC) $(CFLAGS) -c $< diff --git a/fips202.c b/fips202.c index 5e36d66..4565782 100644 --- a/fips202.c @@ -84,58 +136,89 @@ index 58c0619..c55ebaf 100644 /* These are merely internal identifiers for the supported hash functions. */ #define XMSS_SHA2 0 #define XMSS_SHAKE128 1 -diff --git a/hash.c b/thash.c -similarity index 68% -rename from hash.c -rename to thash.c -index 6724d43..e8af5c4 100644 ---- a/hash.c -+++ b/thash.c -@@ -1,12 +1,14 @@ - #include -+#include - #include --#include +diff --git a/randombytes.c b/randombytes.c +index bfc8d93..ba4d7ac 100644 +--- a/randombytes.c ++++ b/randombytes.c +@@ -5,6 +5,8 @@ This code was taken from the SPHINCS reference implementation and is public doma + #include + #include + ++#include "randombytes.h" + + static int fd = -1; + + void randombytes(unsigned char *x, unsigned long long xlen) +diff --git a/test/speed.c b/test/speed.c +index 6ae58b0..93d7d3c 100644 +--- a/test/speed.c ++++ b/test/speed.c +@@ -4,8 +4,13 @@ + + #include "../xmss.h" + #include "../params.h" ++#include "../xmss_callbacks.h" + #include "../randombytes.h" + ++#include +#include -+#include ++#include ++ + #define XMSS_MLEN 32 - #include "hash_address.h" - #include "utils.h" - #include "params.h" --#include "hash.h" --#include "fips202.h" -+#include "thash.h" + #ifndef XMSS_SIGNATURES +@@ -34,6 +39,8 @@ + #endif + #endif - #define XMSS_HASH_PADDING_F 0 - #define XMSS_HASH_PADDING_H 1 -@@ -14,6 +16,69 @@ - #define XMSS_HASH_PADDING_PRF 3 - #define XMSS_HASH_PADDING_PRF_KEYGEN 4 ++static WC_RNG rng; ++ + static unsigned long long cpucycles(void) + { + unsigned long long result; +@@ -78,6 +85,53 @@ static void print_results(unsigned long long *t, size_t tlen) + printf("\n"); + } -+static int sha256(const unsigned char *in, unsigned long long inlen, -+ unsigned char *out) ++static int rng_cb(void * output, size_t length) ++{ ++ int ret = 0; ++ ++ if (output == NULL) { ++ return -1; ++ } ++ ++ if (length == 0) { ++ return 0; ++ } ++ ++ ret = wc_RNG_GenerateBlock(&rng, output, (word32) length); ++ ++ if (ret) { ++ printf("error: xmss rng_cb failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out) +{ + wc_Sha256 sha; + + if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) { -+#if !defined WOLFBOOT_SIGN_XMSS -+ fprintf(stderr, "SHA256 Init failed"); -+#endif ++ printf("SHA256 Init failed"); + return -1; + } + + if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) { -+#if !defined WOLFBOOT_SIGN_XMSS -+ fprintf(stderr, "SHA256 Update failed"); -+#endif ++ printf("SHA256 Update failed"); + return -1; + } + + if (wc_Sha256Final(&sha, out) != 0) { -+#if !defined WOLFBOOT_SIGN_XMSS -+ fprintf(stderr, "SHA256 Final failed"); -+#endif ++ printf("SHA256 Final failed"); + wc_Sha256Free(&sha); + return -1; + } @@ -144,54 +227,685 @@ index 6724d43..e8af5c4 100644 + return 0; +} + -+static int sha512(const unsigned char *in, unsigned long long inlen, -+ unsigned char *out) -+{ -+ /* Disabling everything but sha256 for now. */ -+ (void) in; -+ (void) inlen; -+ (void) out; -+ return -1; -+} -+ -+static int shake128(unsigned char *out, unsigned long long outlen, -+ const unsigned char *in, unsigned long long inlen) -+{ -+ /* Disabling everything but sha256 for now. */ -+ (void) in; -+ (void) inlen; -+ (void) out; -+ (void) outlen; -+ return -1; -+} -+ -+static int shake256(unsigned char *out, unsigned long long outlen, -+ const unsigned char *in, unsigned long long inlen) -+{ -+ /* Disabling everything but sha256 for now. */ -+ (void) in; -+ (void) inlen; -+ (void) out; -+ (void) outlen; -+ return -1; -+} -+ - void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]) + int main() { + /* Make stdout buffer more responsive. */ +@@ -88,6 +142,24 @@ int main() + int ret = 0; int i; -@@ -27,32 +92,39 @@ static int core_hash(const xmss_params *params, + ++ ret = wc_InitRng(&rng); ++ if (ret != 0) { ++ printf("error: init rng failed: %d\n", ret); ++ return -1; ++ } ++ ++ ret = xmss_set_sha_cb(sha256_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_sha_cb failed"); ++ return -1; ++ } ++ ++ ret = xmss_set_rng_cb(rng_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_rng_cb failed"); ++ return -1; ++ } ++ + // TODO test more different variants + if (XMSS_STR_TO_OID(&oid, XMSS_VARIANT)) { + #ifdef XMSSMT +@@ -101,18 +173,18 @@ int main() + + unsigned char pk[XMSS_OID_LEN + params.pk_bytes]; + unsigned char sk[XMSS_OID_LEN + params.sk_bytes]; +- unsigned char *m = malloc(XMSS_MLEN); +- unsigned char *sm = malloc(params.sig_bytes + XMSS_MLEN); +- unsigned char *mout = malloc(params.sig_bytes + XMSS_MLEN); +- unsigned long long smlen; +- unsigned long long mlen; ++ unsigned char *msg = malloc(XMSS_MLEN); ++ unsigned char *sig = malloc(params.sig_bytes); ++ unsigned char *msgout = malloc(XMSS_MLEN); ++ unsigned long long siglen; ++ unsigned long long msglen; + + unsigned long long t0, t1; + unsigned long long *t = malloc(sizeof(unsigned long long) * XMSS_SIGNATURES); + struct timespec start, stop; + double result; + +- randombytes(m, XMSS_MLEN); ++ randombytes(msg, XMSS_MLEN); + + printf("Benchmarking variant %s\n", XMSS_VARIANT); + +@@ -130,7 +202,7 @@ int main() + + for (i = 0; i < XMSS_SIGNATURES; i++) { + t[i] = cpucycles(); +- XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN); ++ XMSS_SIGN(sk, sig, &siglen, msg, XMSS_MLEN); + } + print_results(t, XMSS_SIGNATURES); + +@@ -138,7 +210,7 @@ int main() + + for (i = 0; i < XMSS_SIGNATURES; i++) { + t[i] = cpucycles(); +- ret |= XMSS_SIGN_OPEN(mout, &mlen, sm, smlen, pk); ++ ret |= XMSS_SIGN_OPEN(msgout, &msglen, sig, siglen, pk); + } + print_results(t, XMSS_SIGNATURES); + +@@ -150,10 +222,12 @@ int main() + printf("Public key size: %d (%.2f KiB)\n", params.pk_bytes, params.pk_bytes / 1024.0); + printf("Secret key size: %llu (%.2f KiB)\n", params.sk_bytes, params.sk_bytes / 1024.0); + +- free(m); +- free(sm); +- free(mout); ++ wc_FreeRng(&rng); ++ ++ free(msg); ++ free(sig); ++ free(msgout); + free(t); + + return ret; +-} +\ No newline at end of file ++} +diff --git a/test/wots.c b/test/wots.c +index 8b2b6de..6192527 100644 +--- a/test/wots.c ++++ b/test/wots.c +@@ -3,14 +3,26 @@ + #include + + #include "../wots.h" ++#include "../xmss_callbacks.h" + #include "../randombytes.h" + #include "../params.h" + ++#include ++#include ++#include ++ ++static int rng_cb(void * output, size_t length); ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out); ++ ++static WC_RNG rng; ++ + int main() + { + xmss_params params; + // TODO test more different OIDs + uint32_t oid = 0x00000001; ++ int ret = -1; + + /* For WOTS it doesn't matter if we use XMSS or XMSSMT. */ + xmss_parse_oid(¶ms, oid); +@@ -23,6 +35,24 @@ int main() + unsigned char m[params.n]; + uint32_t addr[8] = {0}; + ++ ret = wc_InitRng(&rng); ++ if (ret != 0) { ++ printf("error: init rng failed: %d\n", ret); ++ return -1; ++ } ++ ++ ret = xmss_set_sha_cb(sha256_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_sha_cb failed"); ++ return -1; ++ } ++ ++ ret = xmss_set_rng_cb(rng_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_rng_cb failed"); ++ return -1; ++ } ++ + randombytes(seed, params.n); + randombytes(pub_seed, params.n); + randombytes(m, params.n); +@@ -41,3 +71,50 @@ int main() + printf("successful.\n"); + return 0; + } ++ ++static int rng_cb(void * output, size_t length) ++{ ++ int ret = 0; ++ ++ if (output == NULL) { ++ return -1; ++ } ++ ++ if (length == 0) { ++ return 0; ++ } ++ ++ ret = wc_RNG_GenerateBlock(&rng, output, (word32) length); ++ ++ if (ret) { ++ printf("error: xmss rng_cb failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out) ++{ ++ wc_Sha256 sha; ++ ++ if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) { ++ printf("SHA256 Init failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) { ++ printf("SHA256 Update failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Final(&sha, out) != 0) { ++ printf("SHA256 Final failed"); ++ wc_Sha256Free(&sha); ++ return -1; ++ } ++ wc_Sha256Free(&sha); ++ ++ return 0; ++} +diff --git a/test/xmss.c b/test/xmss.c +index 3703759..675e4a5 100644 +--- a/test/xmss.c ++++ b/test/xmss.c +@@ -4,9 +4,14 @@ + #include + + #include "../xmss.h" ++#include "../xmss_callbacks.h" + #include "../params.h" + #include "../randombytes.h" + ++#include ++#include ++#include ++ + #define XMSS_MLEN 32 + + #ifndef XMSS_SIGNATURES +@@ -29,6 +34,12 @@ + #define XMSS_VARIANT "XMSS-SHA2_10_256" + #endif + ++static int rng_cb(void * output, size_t length); ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out); ++ ++static WC_RNG rng; ++ + int main() + { + xmss_params params; +@@ -42,13 +53,30 @@ int main() + + unsigned char pk[XMSS_OID_LEN + params.pk_bytes]; + unsigned char sk[XMSS_OID_LEN + params.sk_bytes]; +- unsigned char *m = malloc(XMSS_MLEN); +- unsigned char *sm = malloc(params.sig_bytes + XMSS_MLEN); +- unsigned char *mout = malloc(params.sig_bytes + XMSS_MLEN); +- unsigned long long smlen; +- unsigned long long mlen; ++ unsigned char *msg = malloc(XMSS_MLEN); ++ unsigned char *sig = malloc(params.sig_bytes); ++ unsigned long long siglen = params.sig_bytes; ++ unsigned long long msglen = XMSS_MLEN; ++ ++ ret = wc_InitRng(&rng); ++ if (ret != 0) { ++ printf("error: init rng failed: %d\n", ret); ++ return -1; ++ } + +- randombytes(m, XMSS_MLEN); ++ ret = xmss_set_sha_cb(sha256_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_sha_cb failed"); ++ return -1; ++ } ++ ++ ret = xmss_set_rng_cb(rng_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_rng_cb failed"); ++ return -1; ++ } ++ ++ randombytes(msg, XMSS_MLEN); + + XMSS_KEYPAIR(pk, sk, oid); + +@@ -57,19 +85,19 @@ int main() + for (i = 0; i < XMSS_SIGNATURES; i++) { + printf(" - iteration #%d:\n", i); + +- XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN); ++ XMSS_SIGN(sk, sig, &siglen, msg, XMSS_MLEN); + +- if (smlen != params.sig_bytes + XMSS_MLEN) { +- printf(" X smlen incorrect [%llu != %u]!\n", +- smlen, params.sig_bytes); ++ if (siglen != params.sig_bytes) { ++ printf(" X siglen incorrect [%llu != %u]!\n", ++ siglen, params.sig_bytes); + ret = -1; + } + else { +- printf(" smlen as expected [%llu].\n", smlen); ++ printf(" siglen as expected [%llu].\n", siglen); + } + + /* Test if signature is valid. */ +- if (XMSS_SIGN_OPEN(mout, &mlen, sm, smlen, pk)) { ++ if (XMSS_SIGN_OPEN(msg, &msglen, sig, siglen, pk)) { + printf(" X verification failed!\n"); + ret = -1; + } +@@ -78,57 +106,96 @@ int main() + } + + /* Test if the correct message was recovered. */ +- if (mlen != XMSS_MLEN) { +- printf(" X mlen incorrect [%llu != %u]!\n", mlen, XMSS_MLEN); ++ if (msglen != XMSS_MLEN) { ++ printf(" X msglen incorrect [%llu != %u]!\n", msglen, XMSS_MLEN); + ret = -1; + } + else { +- printf(" mlen as expected [%llu].\n", mlen); +- } +- if (memcmp(m, mout, XMSS_MLEN)) { +- printf(" X output message incorrect!\n"); +- ret = -1; +- } +- else { +- printf(" output message as expected.\n"); ++ printf(" msglen as expected [%llu].\n", msglen); + } + + /* Test if flipping bits invalidates the signature (it should). */ + + /* Flip the first bit of the message. Should invalidate. */ +- sm[smlen - 1] ^= 1; +- if (!XMSS_SIGN_OPEN(mout, &mlen, sm, smlen, pk)) { ++ sig[siglen - 1] ^= 1; ++ if (!XMSS_SIGN_OPEN(msg, &msglen, sig, siglen, pk)) { + printf(" X flipping a bit of m DID NOT invalidate signature!\n"); + ret = -1; + } + else { + printf(" flipping a bit of m invalidates signature.\n"); + } +- sm[smlen - 1] ^= 1; ++ sig[siglen - 1] ^= 1; + + #ifdef XMSS_TEST_INVALIDSIG + int j; + /* Flip one bit per hash; the signature is almost entirely hashes. + This also flips a bit in the index, which is also a useful test. */ +- for (j = 0; j < (int)(smlen - XMSS_MLEN); j += params.n) { +- sm[j] ^= 1; +- if (!XMSS_SIGN_OPEN(mout, &mlen, sm, smlen, pk)) { ++ for (j = 0; j < (int)(siglen - XMSS_MLEN); j += params.n) { ++ sig[j] ^= 1; ++ if (!XMSS_SIGN_OPEN(msg, &msglen, sig, siglen, pk)) { + printf(" X flipping bit %d DID NOT invalidate sig + m!\n", j); +- sm[j] ^= 1; ++ sig[j] ^= 1; + ret = -1; + break; + } +- sm[j] ^= 1; ++ sig[j] ^= 1; + } +- if (j >= (int)(smlen - XMSS_MLEN)) { ++ if (j >= (int)(siglen - XMSS_MLEN)) { + printf(" changing any signature hash invalidates signature.\n"); + } + #endif + } + +- free(m); +- free(sm); +- free(mout); ++ free(msg); ++ free(sig); + + return ret; + } ++ ++static int rng_cb(void * output, size_t length) ++{ ++ int ret = 0; ++ ++ if (output == NULL) { ++ return -1; ++ } ++ ++ if (length == 0) { ++ return 0; ++ } ++ ++ ret = wc_RNG_GenerateBlock(&rng, output, (word32) length); ++ ++ if (ret) { ++ printf("error: xmss rng_cb failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out) ++{ ++ wc_Sha256 sha; ++ ++ if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) { ++ printf("SHA256 Init failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) { ++ printf("SHA256 Update failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Final(&sha, out) != 0) { ++ printf("SHA256 Final failed"); ++ wc_Sha256Free(&sha); ++ return -1; ++ } ++ wc_Sha256Free(&sha); ++ ++ return 0; ++} +diff --git a/test/xmss_determinism.c b/test/xmss_determinism.c +index 49629f8..a309157 100644 +--- a/test/xmss_determinism.c ++++ b/test/xmss_determinism.c +@@ -3,17 +3,47 @@ + #include + + #include "../params.h" ++#include "../xmss_callbacks.h" + #include "../xmss.h" + #include "../randombytes.h" + ++#include ++#include ++#include ++ + #define MLEN 32 + ++static int rng_cb(void * output, size_t length); ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out); ++ ++static WC_RNG rng; ++ + int main() + { + xmss_params params; + char *oidstr = "XMSS-SHA2_10_256"; + uint32_t oid; + unsigned int i; ++ int ret = -1; ++ ++ ret = wc_InitRng(&rng); ++ if (ret != 0) { ++ printf("error: init rng failed: %d\n", ret); ++ return -1; ++ } ++ ++ ret = xmss_set_sha_cb(sha256_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_sha_cb failed"); ++ return -1; ++ } ++ ++ ret = xmss_set_rng_cb(rng_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_rng_cb failed"); ++ return -1; ++ } + + fprintf(stderr, "Testing if XMSS-SHA2_10_256 signing is deterministic.. "); + +@@ -55,3 +85,50 @@ int main() + + return 0; + } ++ ++static int rng_cb(void * output, size_t length) ++{ ++ int ret = 0; ++ ++ if (output == NULL) { ++ return -1; ++ } ++ ++ if (length == 0) { ++ return 0; ++ } ++ ++ ret = wc_RNG_GenerateBlock(&rng, output, (word32) length); ++ ++ if (ret) { ++ printf("error: xmss rng_cb failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out) ++{ ++ wc_Sha256 sha; ++ ++ if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) { ++ printf("SHA256 Init failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) { ++ printf("SHA256 Update failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Final(&sha, out) != 0) { ++ printf("SHA256 Final failed"); ++ wc_Sha256Free(&sha); ++ return -1; ++ } ++ wc_Sha256Free(&sha); ++ ++ return 0; ++} +diff --git a/test/xmss_max_signatures.c b/test/xmss_max_signatures.c +index d4a45a4..b1432da 100644 +--- a/test/xmss_max_signatures.c ++++ b/test/xmss_max_signatures.c +@@ -5,9 +5,14 @@ + + #include "../xmss.h" + #include "../params.h" ++#include "../xmss_callbacks.h" + #include "../randombytes.h" + #include "../utils.h" + ++#include ++#include ++#include ++ + #define XMSS_MLEN 32 + + // #ifndef XMSS_SIGNATURES +@@ -32,6 +37,55 @@ + #define XMSS_SIGNATURES (1 << 10) + #endif + ++static WC_RNG rng; ++ ++static int rng_cb(void * output, size_t length) ++{ ++ int ret = 0; ++ ++ if (output == NULL) { ++ return -1; ++ } ++ ++ if (length == 0) { ++ return 0; ++ } ++ ++ ret = wc_RNG_GenerateBlock(&rng, output, (word32) length); ++ ++ if (ret) { ++ printf("error: xmss rng_cb failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out) ++{ ++ wc_Sha256 sha; ++ ++ if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) { ++ printf("SHA256 Init failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) { ++ printf("SHA256 Update failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Final(&sha, out) != 0) { ++ printf("SHA256 Final failed"); ++ wc_Sha256Free(&sha); ++ return -1; ++ } ++ wc_Sha256Free(&sha); ++ ++ return 0; ++} ++ + int main() + { + xmss_params params; +@@ -53,6 +107,24 @@ int main() + unsigned long long idx; + unsigned long long j; + ++ ret = wc_InitRng(&rng); ++ if (ret != 0) { ++ printf("error: init rng failed: %d\n", ret); ++ return -1; ++ } ++ ++ ret = xmss_set_sha_cb(sha256_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_sha_cb failed"); ++ return -1; ++ } ++ ++ ret = xmss_set_rng_cb(rng_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_rng_cb failed"); ++ return -1; ++ } ++ + randombytes(m, XMSS_MLEN); + + XMSS_KEYPAIR(pk, sk, oid); +diff --git a/hash.c b/thash.c +similarity index 79% +rename from hash.c +rename to thash.c +index 6724d43..54e8954 100644 +--- a/hash.c ++++ b/thash.c +@@ -1,12 +1,14 @@ + #include ++#include + #include +-#include + ++#include "xmss_callbacks.h" + #include "hash_address.h" + #include "utils.h" + #include "params.h" +-#include "hash.h" +-#include "fips202.h" ++#include "thash.h" ++ ++static sha_cb_t sha_cb = NULL; + + #define XMSS_HASH_PADDING_F 0 + #define XMSS_HASH_PADDING_H 1 +@@ -22,37 +24,67 @@ void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]) + } + } + ++int xmss_set_sha_cb(sha_cb_t cb) ++{ ++ if (cb == NULL) { ++ return -1; ++ } ++ ++ sha_cb = cb; ++ ++ return 0; ++} ++ + static int core_hash(const xmss_params *params, + unsigned char *out, const unsigned char *in, unsigned long long inlen) { - unsigned char buf[64]; -+ int ret = -1; +- unsigned char buf[64]; ++ int ret = -1; + ++ if (sha_cb == NULL) { ++ return -1; ++ } + + if (params == NULL || out == NULL || in == NULL) { + return -1; + } - ++ ++ /* The choice of SHA256 and n=32 is set at compile time. */ ++ if (params->n != XMSS_SHA256_N || params->func != XMSS_SHA2) { ++ return -1; ++ } ++ ++ ret = sha_cb(in, inlen, out); ++ ++/* if (params->n == 24 && params->func == XMSS_SHA2) { - SHA256(in, inlen, buf); -+ ret = sha256(in, inlen, buf); ++ ret = sha_cb(in, inlen, out); memcpy(out, buf, 24); } else if (params->n == 24 && params->func == XMSS_SHAKE256) { @@ -200,7 +914,7 @@ index 6724d43..e8af5c4 100644 } else if (params->n == 32 && params->func == XMSS_SHA2) { - SHA256(in, inlen, out); -+ ret = sha256(in, inlen, out); ++ ret = sha_cb(in, inlen, out); } else if (params->n == 32 && params->func == XMSS_SHAKE128) { - shake128(out, 32, in, inlen); @@ -221,12 +935,13 @@ index 6724d43..e8af5c4 100644 else { return -1; } ++*/ + + if (ret != 0) { return ret; } return 0; } -@@ -63,7 +135,11 @@ int prf(const xmss_params *params, +@@ -63,7 +95,11 @@ int prf(const xmss_params *params, unsigned char *out, const unsigned char in[32], const unsigned char *key) { @@ -238,7 +953,7 @@ index 6724d43..e8af5c4 100644 ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF); memcpy(buf + params->padding_len, key, params->n); -@@ -80,7 +156,11 @@ int prf_keygen(const xmss_params *params, +@@ -80,7 +116,11 @@ int prf_keygen(const xmss_params *params, unsigned char *out, const unsigned char *in, const unsigned char *key) { @@ -250,7 +965,7 @@ index 6724d43..e8af5c4 100644 ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF_KEYGEN); memcpy(buf + params->padding_len, key, params->n); -@@ -118,8 +198,13 @@ int thash_h(const xmss_params *params, +@@ -118,8 +158,13 @@ int thash_h(const xmss_params *params, unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]) { @@ -264,7 +979,7 @@ index 6724d43..e8af5c4 100644 unsigned char addr_as_bytes[32]; unsigned int i; -@@ -150,8 +235,13 @@ int thash_f(const xmss_params *params, +@@ -150,8 +195,13 @@ int thash_f(const xmss_params *params, unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8]) { @@ -279,11 +994,130 @@ index 6724d43..e8af5c4 100644 unsigned int i; diff --git a/hash.h b/thash.h -similarity index 100% +similarity index 96% rename from hash.h rename to thash.h +index 6e13d12..dcfb781 100644 +--- a/hash.h ++++ b/thash.h +@@ -1,9 +1,10 @@ +-#ifndef XMSS_HASH_H +-#define XMSS_HASH_H ++#ifndef XMSS_THASH_H ++#define XMSS_THASH_H + + #include + #include "params.h" + ++ + void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8]); + + int prf(const xmss_params *params, +diff --git a/ui/keypair.c b/ui/keypair.c +index 612c448..64dc067 100644 +--- a/ui/keypair.c ++++ b/ui/keypair.c +@@ -3,6 +3,11 @@ + + #include "../params.h" + #include "../xmss.h" ++#include "../xmss_callbacks.h" ++ ++#include ++#include ++#include + + #ifdef XMSSMT + #define XMSS_STR_TO_OID xmssmt_str_to_oid +@@ -14,11 +19,61 @@ + #define XMSS_KEYPAIR xmss_keypair + #endif + ++static WC_RNG rng; ++ ++static int rng_cb(void * output, size_t length) ++{ ++ int ret = 0; ++ ++ if (output == NULL) { ++ return -1; ++ } ++ ++ if (length == 0) { ++ return 0; ++ } ++ ++ ret = wc_RNG_GenerateBlock(&rng, output, (word32) length); ++ ++ if (ret) { ++ printf("error: xmss rng_cb failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int sha256_cb(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out) ++{ ++ wc_Sha256 sha; ++ ++ if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) { ++ printf("SHA256 Init failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) { ++ printf("SHA256 Update failed"); ++ return -1; ++ } ++ ++ if (wc_Sha256Final(&sha, out) != 0) { ++ printf("SHA256 Final failed"); ++ wc_Sha256Free(&sha); ++ return -1; ++ } ++ wc_Sha256Free(&sha); ++ ++ return 0; ++} ++ + int main(int argc, char **argv) + { + xmss_params params; + uint32_t oid = 0; + int parse_oid_result = 0; ++ int ret = -1; + + if (argc != 2) { + fprintf(stderr, "Expected parameter string (e.g. 'XMSS-SHA2_10_256')" +@@ -27,6 +82,24 @@ int main(int argc, char **argv) + return -1; + } + ++ ret = wc_InitRng(&rng); ++ if (ret != 0) { ++ printf("error: init rng failed: %d\n", ret); ++ return -1; ++ } ++ ++ ret = xmss_set_sha_cb(sha256_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_sha_cb failed"); ++ return -1; ++ } ++ ++ ret = xmss_set_rng_cb(rng_cb); ++ if (ret != 0) { ++ printf("error: xmss_set_rng_cb failed"); ++ return -1; ++ } ++ + XMSS_STR_TO_OID(&oid, argv[1]); + parse_oid_result = XMSS_PARSE_OID(¶ms, oid); + if (parse_oid_result != 0) { diff --git a/wots.c b/wots.c -index d9c8449..8acb313 100644 +index d9c8449..825c2dc 100644 --- a/wots.c +++ b/wots.c @@ -2,7 +2,7 @@ @@ -307,7 +1141,7 @@ index d9c8449..8acb313 100644 set_hash_addr(addr, 0); set_key_and_mask(addr, 0); -@@ -83,7 +87,25 @@ static void wots_checksum(const xmss_params *params, +@@ -83,7 +87,23 @@ static void wots_checksum(const xmss_params *params, int *csum_base_w, const int *msg_base_w) { int csum = 0; @@ -322,8 +1156,6 @@ index d9c8449..8acb313 100644 + * + * Therefore: + * -+ * (params->wots_len2 * params->wots_log_w + 7) / 8 = 2 -+ * + * (3 * 4 + 7) / 8 = 2 + * */ + unsigned char csum_bytes[2]; @@ -333,7 +1165,7 @@ index d9c8449..8acb313 100644 unsigned int i; /* Compute checksum. */ -@@ -94,7 +116,7 @@ static void wots_checksum(const xmss_params *params, +@@ -94,7 +114,7 @@ static void wots_checksum(const xmss_params *params, /* Convert checksum to base_w. */ /* Make sure expected empty zero bits are the least significant bits. */ csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8)); @@ -342,20 +1174,17 @@ index d9c8449..8acb313 100644 base_w(params, csum_base_w, params->wots_len2, csum_bytes); } -@@ -139,7 +161,12 @@ void wots_sign(const xmss_params *params, +@@ -139,7 +159,8 @@ void wots_sign(const xmss_params *params, const unsigned char *seed, const unsigned char *pub_seed, uint32_t addr[8]) { -+#if defined WOLFBOOT_SIGN_XMSS -+ int lengths[XMSS_SHA256_WOTS_LEN]; -+#else - int lengths[params->wots_len]; -+#endif -+ +- int lengths[params->wots_len]; ++ /* int lengths[params->wots_len]; */ ++ int lengths[67]; uint32_t i; chain_lengths(params, lengths, msg); -@@ -163,7 +190,11 @@ void wots_pk_from_sig(const xmss_params *params, unsigned char *pk, +@@ -163,7 +184,11 @@ void wots_pk_from_sig(const xmss_params *params, unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const unsigned char *pub_seed, uint32_t addr[8]) { @@ -368,7 +1197,7 @@ index d9c8449..8acb313 100644 chain_lengths(params, lengths, msg); diff --git a/xmss.c b/xmss.c -index 9030f6e..faaa000 100644 +index 9030f6e..dbae7e5 100644 --- a/xmss.c +++ b/xmss.c @@ -1,5 +1,6 @@ @@ -378,28 +1207,15 @@ index 9030f6e..faaa000 100644 #include "params.h" #include "xmss_core.h" -@@ -7,7 +8,9 @@ +@@ -7,6 +8,7 @@ identify the parameter set to be used. After setting the parameters accordingly it falls back to the regular XMSS core functions. */ --int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) +#ifndef XMSS_VERIFY_ONLY -+int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid, -+ void * rng) + int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) { xmss_params params; - unsigned int i; -@@ -22,7 +25,8 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) - i.e. not just for interoperability, but also for internal use. */ - sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; - } -- return xmss_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); -+ return xmss_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN, -+ rng); - } - - int xmss_sign(unsigned char *sk, -@@ -42,24 +46,8 @@ int xmss_sign(unsigned char *sk, +@@ -42,23 +44,6 @@ int xmss_sign(unsigned char *sk, return xmss_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); } @@ -420,23 +1236,10 @@ index 9030f6e..faaa000 100644 - 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, -+ void * rng) + int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) { xmss_params params; - unsigned int i; -@@ -71,7 +59,8 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) - pk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; - sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF; - } -- return xmssmt_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); -+ return xmssmt_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN, -+ rng); - } - - int xmssmt_sign(unsigned char *sk, -@@ -90,8 +79,26 @@ int xmssmt_sign(unsigned char *sk, +@@ -90,8 +75,26 @@ int xmssmt_sign(unsigned char *sk, } return xmssmt_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); } @@ -464,7 +1267,7 @@ index 9030f6e..faaa000 100644 const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { -@@ -105,5 +112,5 @@ int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen, +@@ -105,5 +108,5 @@ int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen, if (xmssmt_parse_oid(¶ms, oid)) { return -1; } @@ -472,10 +1275,10 @@ index 9030f6e..faaa000 100644 + return xmssmt_core_sign_open(¶ms, msg, msglen, sm, smlen, pk + XMSS_OID_LEN); } diff --git a/xmss.h b/xmss.h -index c7b4b69..8f4bab4 100644 +index c7b4b69..199ce88 100644 --- a/xmss.h +++ b/xmss.h -@@ -3,50 +3,54 @@ +@@ -3,6 +3,7 @@ #include @@ -483,12 +1286,7 @@ index c7b4b69..8f4bab4 100644 /** * Generates a XMSS key pair for a given parameter set. * Format sk: [OID || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [OID || root || PUB_SEED] - */ --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, -+ void * rng); - +@@ -13,24 +14,13 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid); /** * Signs a message using an XMSS secret key. * Returns @@ -514,12 +1312,7 @@ index c7b4b69..8f4bab4 100644 /* * Generates a XMSSMT key pair for a given parameter set. * Format sk: [OID || (ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [OID || root || PUB_SEED] - */ --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, -+ void * rng); - +@@ -41,12 +31,24 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid); /** * Signs a message using an XMSSMT secret key. * Returns @@ -545,7 +1338,7 @@ index c7b4b69..8f4bab4 100644 /** * Verifies a given message signature pair using a given public key. -@@ -55,7 +59,7 @@ int xmssmt_sign(unsigned char *sk, +@@ -55,7 +57,7 @@ int xmssmt_sign(unsigned char *sk, * verification succeeds. The (input) message is assumed to be contained in sm * which has the form [signature || message]. */ @@ -554,6 +1347,24 @@ index c7b4b69..8f4bab4 100644 const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); #endif +diff --git a/xmss_callbacks.h b/xmss_callbacks.h +new file mode 100644 +index 0000000..31bd300 +--- /dev/null ++++ b/xmss_callbacks.h +@@ -0,0 +1,12 @@ ++#ifndef XMSS_CALLBACKS_H ++#define XMSS_CALLBACKS_H ++ ++/* Callback used for SHA and RNG operations. */ ++typedef int (*sha_cb_t)(const unsigned char *in, unsigned long long inlen, ++ unsigned char *out); ++typedef int (*rng_cb_t)(void * output, size_t length); ++ ++int xmss_set_sha_cb(sha_cb_t cb); ++int xmss_set_rng_cb(rng_cb_t cb); ++ ++#endif diff --git a/xmss_commons.c b/xmss_commons.c index 2b76b94..0599a76 100644 --- a/xmss_commons.c @@ -758,10 +1569,10 @@ index 9d9f077..33dbffe 100644 const unsigned char *pk); #endif diff --git a/xmss_core.c b/xmss_core.c -index af9f8d1..6d3b2f1 100644 +index af9f8d1..e80175b 100644 --- a/xmss_core.c +++ b/xmss_core.c -@@ -2,15 +2,19 @@ +@@ -2,15 +2,47 @@ #include #include @@ -775,26 +1586,61 @@ index af9f8d1..6d3b2f1 100644 #include "xmss_commons.h" #include "xmss_core.h" -+#include -+#include -+#include -+#include ++#ifndef XMSS_VERIFY_ONLY ++#include "xmss_callbacks.h" ++ ++static rng_cb_t rng_cb = NULL; ++ ++typedef struct{ ++ unsigned char h; ++ unsigned long next_idx; ++ unsigned char stackusage; ++ unsigned char completed; ++ unsigned char *node; ++} treehash_inst; ++ ++typedef struct { ++ unsigned char *stack; ++ unsigned int stackoffset; ++ unsigned char *stacklevels; ++ unsigned char *auth; ++ unsigned char *keep; ++ treehash_inst *treehash; ++ unsigned char *retain; ++ unsigned int next_leaf; ++} bds_state; ++ ++int xmss_set_rng_cb(rng_cb_t cb) ++{ ++ if (cb == NULL) { ++ return -1; ++ } ++ rng_cb = cb; ++ return 0; ++} + /** * For a given leaf index, computes the authentication path and the resulting * root node using Merkle's TreeHash algorithm. -@@ -101,28 +105,28 @@ unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) - * Format pk: [root || PUB_SEED], omitting algorithm OID. - */ - int xmss_core_keypair(const xmss_params *params, -- unsigned char *pk, unsigned char *sk) -+ unsigned char *pk, unsigned char *sk, void * rng) - { - /* The key generation procedure of XMSS and XMSSMT is exactly the same. - The only important detail is that the right subtree must be selected; - this requires us to correctly set the d=1 parameter for XMSS. */ -- return xmssmt_core_keypair(params, pk, sk); -+ return xmssmt_core_keypair(params, pk, sk, rng); +@@ -85,6 +117,8 @@ static void treehash(const xmss_params *params, + memcpy(root, stack, params->n); + } + ++#endif /* ifndef XMSS_VERIFY_ONLY */ ++ + /** + * Given a set of parameters, this function returns the size of the secret key. + * This is implementation specific, as varying choices in tree traversal will +@@ -95,6 +129,8 @@ unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) + return params->index_bytes + 4 * params->n; + } + ++#ifndef XMSS_VERIFY_ONLY ++ + /* + * Generates a XMSS key pair for a given parameter set. + * Format sk: [(32bit) index || SK_SEED || SK_PRF || root || PUB_SEED] +@@ -110,19 +146,19 @@ int xmss_core_keypair(const xmss_params *params, } /** @@ -819,21 +1665,16 @@ index af9f8d1..6d3b2f1 100644 } /* -@@ -166,11 +170,19 @@ int xmssmt_core_seed_keypair(const xmss_params *params, - * Format pk: [root || PUB_SEED] omitting algorithm OID. - */ - int xmssmt_core_keypair(const xmss_params *params, -- unsigned char *pk, unsigned char *sk) -+ unsigned char *pk, unsigned char *sk, -+ void * rng) +@@ -169,8 +205,15 @@ int xmssmt_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk) { unsigned char seed[3 * params->n]; + int ret = 0; + -+ ret = wc_RNG_GenerateBlock(rng, seed, (word32) sizeof(seed)); ++ //ret = wc_RNG_GenerateBlock(rng, seed, (word32) sizeof(seed)); ++ ret = rng_cb(seed, sizeof(seed)); + + if (ret != 0) { -+ fprintf(stderr, "error: wc_RNG_GenerateBlock failed: %d\n", ret); + return -1; + } @@ -841,11 +1682,16 @@ index af9f8d1..6d3b2f1 100644 xmssmt_core_seed_keypair(params, pk, sk, seed); return 0; +@@ -271,3 +314,4 @@ int xmssmt_core_sign(const xmss_params *params, + + return 0; + } ++#endif /* ifndef XMSS_VERIFY_ONLY */ diff --git a/xmss_core.h b/xmss_core.h -index e83bc7d..bc1d0c2 100644 +index e83bc7d..21d72ef 100644 --- a/xmss_core.h +++ b/xmss_core.h -@@ -12,13 +12,14 @@ +@@ -12,6 +12,7 @@ */ unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params); @@ -853,15 +1699,7 @@ index e83bc7d..bc1d0c2 100644 /* * Generates a XMSS key pair for a given parameter set. * Format sk: [(32bit) index || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED], omitting algorithm OID. - */ - int xmss_core_keypair(const xmss_params *params, -- unsigned char *pk, unsigned char *sk); -+ unsigned char *pk, unsigned char *sk, void * rng); - - /** - * Signs a message. Returns an array containing the signature followed by the -@@ -29,22 +30,13 @@ int xmss_core_sign(const xmss_params *params, +@@ -29,15 +30,6 @@ int xmss_core_sign(const xmss_params *params, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen); @@ -877,14 +1715,6 @@ index e83bc7d..bc1d0c2 100644 /* * Generates a XMSSMT key pair for a given parameter set. * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] omitting algorithm OID. - */ - int xmssmt_core_keypair(const xmss_params *params, -- unsigned char *pk, unsigned char *sk); -+ unsigned char *pk, unsigned char *sk, void * rng); - - /* - * Derives a XMSSMT key pair for a given parameter set. @@ -64,13 +56,23 @@ int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, @@ -911,10 +1741,10 @@ index e83bc7d..bc1d0c2 100644 const unsigned char *pk); diff --git a/xmss_core_fast.c b/xmss_core_fast.c -index cbf87ec..7d75a22 100644 +index cbf87ec..1a71c07 100644 --- a/xmss_core_fast.c +++ b/xmss_core_fast.c -@@ -2,15 +2,21 @@ +@@ -2,15 +2,19 @@ #include #include @@ -928,17 +1758,31 @@ index cbf87ec..7d75a22 100644 #include "xmss_commons.h" #include "xmss_core.h" -+#include -+#include -+#include -+#include -+ +#ifndef XMSS_VERIFY_ONLY ++#include "xmss_callbacks.h" ++ ++static rng_cb_t rng_cb = NULL; + typedef struct{ unsigned char h; unsigned long next_idx; -@@ -94,7 +100,7 @@ static void xmssmt_deserialize_state(const xmss_params *params, +@@ -30,6 +34,15 @@ typedef struct { + unsigned int next_leaf; + } bds_state; + ++int xmss_set_rng_cb(rng_cb_t cb) ++{ ++ if (cb == NULL) { ++ return -1; ++ } ++ rng_cb = cb; ++ return 0; ++} ++ + /* These serialization functions provide a transition between the current + way of storing the state in an exposed struct, and storing it as part of the + byte array that is the secret key. +@@ -94,7 +107,7 @@ static void xmssmt_deserialize_state(const xmss_params *params, states[i].stack = sk; sk += (params->tree_height + 1) * params->n; @@ -947,7 +1791,7 @@ index cbf87ec..7d75a22 100644 sk += 4; states[i].stacklevels = sk; -@@ -126,7 +132,7 @@ static void xmssmt_deserialize_state(const xmss_params *params, +@@ -126,7 +139,7 @@ static void xmssmt_deserialize_state(const xmss_params *params, states[i].retain = sk; sk += ((1 << params->bds_k) - params->bds_k - 1) * params->n; @@ -956,7 +1800,7 @@ index cbf87ec..7d75a22 100644 sk += 4; } -@@ -299,8 +305,8 @@ static void treehash_update(const xmss_params *params, +@@ -299,8 +312,8 @@ static void treehash_update(const xmss_params *params, copy_subtree_addr(node_addr, addr); set_type(node_addr, 2); @@ -967,7 +1811,7 @@ index cbf87ec..7d75a22 100644 unsigned char nodebuffer[2 * params->n]; unsigned int nodeheight = 0; -@@ -309,7 +315,7 @@ static void treehash_update(const xmss_params *params, +@@ -309,7 +322,7 @@ static void treehash_update(const xmss_params *params, memcpy(nodebuffer + params->n, nodebuffer, params->n); memcpy(nodebuffer, state->stack + (state->stackoffset-1)*params->n, params->n); set_tree_height(node_addr, nodeheight); @@ -976,7 +1820,7 @@ index cbf87ec..7d75a22 100644 thash_h(params, nodebuffer, nodebuffer, pub_seed, node_addr); nodeheight++; treehash->stackusage--; -@@ -476,13 +482,13 @@ static void bds_round(const xmss_params *params, +@@ -476,13 +489,13 @@ static void bds_round(const xmss_params *params, memcpy(state->keep + (tau >> 1)*params->n, state->auth + tau*params->n, params->n); } if (tau == 0) { @@ -993,7 +1837,7 @@ index cbf87ec..7d75a22 100644 thash_h(params, state->auth + tau * params->n, buf, pub_seed, node_addr); for (i = 0; i < tau; i++) { if (i < params->tree_height - params->bds_k) { -@@ -490,13 +496,13 @@ static void bds_round(const xmss_params *params, +@@ -490,13 +503,13 @@ static void bds_round(const xmss_params *params, } else { offset = (1 << (params->tree_height - 1 - i)) + i - params->tree_height; @@ -1009,7 +1853,7 @@ index cbf87ec..7d75a22 100644 if (startidx < 1U << params->tree_height) { state->treehash[i].h = i; state->treehash[i].next_idx = startidx; -@@ -507,6 +513,8 @@ static void bds_round(const xmss_params *params, +@@ -507,6 +520,8 @@ static void bds_round(const xmss_params *params, } } @@ -1018,7 +1862,7 @@ index cbf87ec..7d75a22 100644 /** * Given a set of parameters, this function returns the size of the secret key. * This is implementation specific, as varying choices in tree traversal will -@@ -530,15 +538,18 @@ unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) +@@ -530,6 +545,7 @@ unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params) + (params->d - 1) * params->wots_sig_bytes; } @@ -1026,34 +1870,34 @@ index cbf87ec..7d75a22 100644 /* * Generates a XMSS key pair for a given parameter set. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || root || PUB_SEED] - * Format pk: [root || PUB_SEED] omitting algo oid. - */ - int xmss_core_keypair(const xmss_params *params, -- unsigned char *pk, unsigned char *sk) -+ unsigned char *pk, unsigned char *sk, -+ void * rng) +@@ -539,6 +555,7 @@ int xmss_core_keypair(const xmss_params *params, + unsigned char *pk, unsigned char *sk) { uint32_t addr[8] = {0}; + int ret = 0; // TODO refactor BDS state not to need separate treehash instances bds_state state; -@@ -555,16 +566,27 @@ int xmss_core_keypair(const xmss_params *params, +@@ -555,16 +572,31 @@ int xmss_core_keypair(const xmss_params *params, sk[1] = 0; sk[2] = 0; sk[3] = 0; + // Init SK_SEED (n byte) and SK_PRF (n byte) - randombytes(sk + params->index_bytes, 2*params->n); -+ ret = wc_RNG_GenerateBlock(rng, sk + params->index_bytes, -+ (word32) 2*params->n); ++ //ret = wc_RNG_GenerateBlock(rng, sk + params->index_bytes, ++ // (word32) 2*params->n); ++ ++ ret = rng_cb(sk + params->index_bytes, 2*params->n); + + if (ret != 0) { return -1; } // Init PUB_SEED (n byte) - randombytes(sk + params->index_bytes + 3*params->n, params->n); -+ ret = wc_RNG_GenerateBlock(rng, sk + params->index_bytes + 3*params->n, -+ (word32) params->n); ++ //ret = wc_RNG_GenerateBlock(rng, sk + params->index_bytes + 3*params->n, ++ // (word32) params->n); ++ ++ ret = rng_cb(sk + params->index_bytes + 3*params->n, params->n); + + if (ret != 0) { return -1; } + @@ -1069,7 +1913,7 @@ index cbf87ec..7d75a22 100644 // copy root to sk memcpy(sk + params->index_bytes + 2*params->n, pk, params->n); -@@ -577,19 +599,39 @@ int xmss_core_keypair(const xmss_params *params, +@@ -577,19 +609,39 @@ int xmss_core_keypair(const xmss_params *params, /** * Signs a message. * Returns @@ -1112,7 +1956,7 @@ index cbf87ec..7d75a22 100644 // TODO refactor BDS state not to need separate treehash instances bds_state state; treehash_inst treehash[params->tree_height - params->bds_k]; -@@ -599,7 +641,9 @@ int xmss_core_sign(const xmss_params *params, +@@ -599,7 +651,9 @@ int xmss_core_sign(const xmss_params *params, xmss_deserialize_state(params, &state, sk); // Extract SK @@ -1123,7 +1967,7 @@ index cbf87ec..7d75a22 100644 /* Check if we can still sign with this sk. * If not, return -2 -@@ -658,32 +702,32 @@ int xmss_core_sign(const xmss_params *params, +@@ -658,32 +712,32 @@ int xmss_core_sign(const xmss_params *params, /* Already put the message in the right place, to make it easier to prepend * things when computing the hash over the message. */ @@ -1169,7 +2013,7 @@ index cbf87ec..7d75a22 100644 // ---------------------------------- // Now we start to "really sign" -@@ -691,27 +735,24 @@ int xmss_core_sign(const xmss_params *params, +@@ -691,27 +745,24 @@ int xmss_core_sign(const xmss_params *params, // Prepare Address set_type(ots_addr, 0); @@ -1204,12 +2048,9 @@ index cbf87ec..7d75a22 100644 /* Write the updated BDS state back into sk. */ xmss_serialize_state(params, sk, &state); -@@ -725,11 +766,12 @@ int xmss_core_sign(const xmss_params *params, - * Format pk: [root || PUB_SEED] omitting algo oid. - */ +@@ -727,9 +778,10 @@ int xmss_core_sign(const xmss_params *params, int xmssmt_core_keypair(const xmss_params *params, -- unsigned char *pk, unsigned char *sk) -+ unsigned char *pk, unsigned char *sk, void * rng) + unsigned char *pk, unsigned char *sk) { - uint32_t addr[8] = {0}; - unsigned int i; @@ -1221,27 +2062,29 @@ index cbf87ec..7d75a22 100644 // TODO refactor BDS state not to need separate treehash instances bds_state states[2*params->d - 1]; -@@ -750,10 +792,17 @@ int xmssmt_core_keypair(const xmss_params *params, +@@ -750,10 +802,19 @@ int xmssmt_core_keypair(const xmss_params *params, sk[i] = 0; } // Init SK_SEED (params->n byte) and SK_PRF (params->n byte) - randombytes(sk+params->index_bytes, 2*params->n); -+ ret = wc_RNG_GenerateBlock(rng, sk+params->index_bytes, -+ (word32) 2*params->n); ++ //ret = wc_RNG_GenerateBlock(rng, sk+params->index_bytes, ++ // (word32) 2*params->n); ++ ret = rng_cb(sk+params->index_bytes, 2*params->n); + + if (ret != 0) { return -1; } // Init PUB_SEED (params->n byte) - randombytes(sk+params->index_bytes + 3*params->n, params->n); -+ ret = wc_RNG_GenerateBlock(rng, sk+params->index_bytes + 3*params->n, -+ (word32) params->n); ++ //ret = wc_RNG_GenerateBlock(rng, sk+params->index_bytes + 3*params->n, ++ // (word32) params->n); ++ ret = rng_cb(sk+params->index_bytes + 3*params->n, params->n); + + if (ret != 0) { return -1; } + // Copy PUB_SEED to public key memcpy(pk+params->n, sk+params->index_bytes+3*params->n, params->n); -@@ -778,17 +827,37 @@ int xmssmt_core_keypair(const xmss_params *params, +@@ -778,17 +839,37 @@ int xmssmt_core_keypair(const xmss_params *params, /** * Signs a message. * Returns @@ -1282,7 +2125,7 @@ index cbf87ec..7d75a22 100644 uint64_t idx_tree; uint32_t idx_leaf; uint64_t i, j; -@@ -867,31 +936,34 @@ int xmssmt_core_sign(const xmss_params *params, +@@ -867,31 +948,34 @@ int xmssmt_core_sign(const xmss_params *params, /* Already put the message in the right place, to make it easier to prepend * things when computing the hash over the message. */ @@ -1327,7 +2170,7 @@ index cbf87ec..7d75a22 100644 // ---------------------------------- // Now we start to "really sign" -@@ -908,27 +980,27 @@ int xmssmt_core_sign(const xmss_params *params, +@@ -908,27 +992,27 @@ int xmssmt_core_sign(const xmss_params *params, set_ots_addr(ots_addr, idx_leaf); // Compute WOTS signature @@ -1367,7 +2210,7 @@ index cbf87ec..7d75a22 100644 } updates = (params->tree_height - params->bds_k) >> 1; -@@ -944,7 +1016,7 @@ int xmssmt_core_sign(const xmss_params *params, +@@ -944,7 +1028,7 @@ int xmssmt_core_sign(const xmss_params *params, 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))); @@ -1376,7 +2219,7 @@ index cbf87ec..7d75a22 100644 set_tree_addr(addr, idx_tree); if (i == (unsigned int) (needswap_upto + 1)) { bds_round(params, &states[i], idx_leaf, sk_seed, pub_seed, addr); -@@ -962,7 +1034,7 @@ int xmssmt_core_sign(const xmss_params *params, +@@ -962,7 +1046,7 @@ int xmssmt_core_sign(const xmss_params *params, else if (idx < (1ULL << params->full_height) - 1) { deep_state_swap(params, states+params->d + i, states + i); @@ -1385,7 +2228,7 @@ index cbf87ec..7d75a22 100644 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))); -@@ -972,17 +1044,15 @@ int xmssmt_core_sign(const xmss_params *params, +@@ -972,17 +1056,15 @@ int xmssmt_core_sign(const xmss_params *params, states[params->d + i].next_leaf = 0; updates--; // WOTS-signing counts as one update diff --git a/pq/stateful_hash_sig/Makefile b/pq/stateful_hash_sig/Makefile index 8924b11b..52c34244 100644 --- a/pq/stateful_hash_sig/Makefile +++ b/pq/stateful_hash_sig/Makefile @@ -10,6 +10,7 @@ LIBS = -L$(LIB_PATH)/lib -lm WOLF_DYN_LIB = -lwolfssl WOLF_STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a HSS_LIB = +XMSS_LIB = DEBUG_FLAGS = -g -DDEBUG DEBUG_INC_PATHS = -MD OPTIMIZE = -Os @@ -34,10 +35,10 @@ lms_example: lms_example.c $(CC) -o $@ $< $(CFLAGS) -I$(HSS_INC) $(LIBS) $(WOLF_STATIC_LIB) $(HSS_LIB) xmss_example: xmss_example.c - $(CC) -o $@ $< $(CFLAGS) -I$(XMSS_INC) $(LIBS) $(WOLF_DYN_LIB) + $(CC) -o $@ $< $(CFLAGS) -I$(XMSS_INC) $(LIBS) $(WOLF_STATIC_LIB) $(XMSS_LIB) xmss_example_verifyonly: xmss_example.c - $(CC) -o $@ $< $(CFLAGS) -I$(XMSS_INC) -DWOLFSSL_XMSS_VERIFY_ONLY $(LIBS) $(WOLF_DYN_LIB) + $(CC) -o $@ $< $(CFLAGS) -I$(XMSS_INC) -DWOLFSSL_XMSS_VERIFY_ONLY $(LIBS) $(WOLF_STATIC_LIB) $(XMSS_LIB) clean: rm -f $(TARGETS) diff --git a/pq/stateful_hash_sig/README.md b/pq/stateful_hash_sig/README.md index 0a1a3d01..a0d0031c 100644 --- a/pq/stateful_hash_sig/README.md +++ b/pq/stateful_hash_sig/README.md @@ -19,9 +19,9 @@ in the wolfSSL repo's INSTALL file. https://github.com/wolfSSL/wolfssl/blob/master/INSTALL The XMSS/XMSS^MT example requires that the xmss-reference repository has been -cloned and patched. Please see item 20 in the wolfSSL repo's INSTALL file. +cloned, patched, and built. Please see item 20 in the wolfSSL repo's INSTALL file. -The patch to use is `0001-Patch-to-support-xmss-reference-integration.patch` from this XMSS/XMSS^MT example. +The patch to use is `0001-Patch-to-support-wolfSSL-xmss-reference-integration.patch` from this XMSS/XMSS^MT example. # Building the LMS/HSS example @@ -84,22 +84,11 @@ Configure the Makefile to point to your xmss install: XMSS_INC = ``` -Nothing more is needed after patching, as wolfSSL will automatically -build and link the xmss-reference objects it needs. - -Build wolfSSL XMSS/XMSS^MT hooks support with: - ``` -$ ./configure \ - --enable-xmss \ - --with-libxmss= -$ make +XMSS_LIB = ``` -Note that depending on your architecture you may add `--enable-intelasm` -or `--enable-armasm` to speedup the XMSS/XMSS^MT hash operations. - -Asumming wolfSSL has been built, you may finally build the xmss example with: +Then build: ``` $ make xmss_example @@ -110,7 +99,6 @@ Build the verify-only example with $ make xmss_example_verifyonly ``` - ## Signing and Verifying a Message with XMSS/XMSS^MT To see the help and usage, run the program without options: diff --git a/pq/stateful_hash_sig/xmss_example.c b/pq/stateful_hash_sig/xmss_example.c index 2707b9f1..0913d135 100644 --- a/pq/stateful_hash_sig/xmss_example.c +++ b/pq/stateful_hash_sig/xmss_example.c @@ -271,6 +271,8 @@ do_xmss_example(const char * params, goto exit_xmss_example; } + printf("making key with %s parameters...\n", params); + ret = wc_XmssKey_MakeKey(&signingKey, &rng); if (ret) { fprintf(stderr, "error: wc_XmssKey_MakeKey returned %d\n", ret);