From 99503968a914ed74693eb0e10199fe3cfa83d652 Mon Sep 17 00:00:00 2001
From: jordan <jordan@wolfssl.com>
Date: Fri, 13 Oct 2023 13:29:46 -0500
Subject: [PATCH 1/1] Patch to support wolfSSL xmss-reference integration.

---
 Makefile                   |  29 +++-
 fips202.c                  |   2 +-
 hash_address.c             |   2 +
 params.h                   |  15 ++
 patch_readme.md            |  42 ++++++
 randombytes.c              |   2 +
 test/oid.c                 |   2 +-
 test/speed.c               | 103 ++++++++++++--
 test/vectors.c             |   4 +-
 test/wots.c                |  79 ++++++++++-
 test/xmss.c                | 141 ++++++++++++++-----
 test/xmss_determinism.c    |  97 +++++++++++--
 test/xmss_max_signatures.c | 102 ++++++++++++--
 hash.c => thash.c          |  72 ++++++----
 hash.h => thash.h          |   5 +-
 ui/keypair.c               |  73 ++++++++++
 wots.c                     |  33 ++++-
 xmss.c                     |  49 +++----
 xmss.h                     |  48 +++----
 xmss_callbacks.h           |  12 ++
 xmss_commons.c             |  77 +++++++----
 xmss_commons.h             |   4 +-
 xmss_core.c                | 135 +++++++++++++-----
 xmss_core.h                |  22 +--
 xmss_core_fast.c           | 276 ++++++++++++++++++++++++-------------
 25 files changed, 1099 insertions(+), 327 deletions(-)
 create mode 100644 patch_readme.md
 rename hash.c => thash.c (82%)
 rename hash.h => thash.h (96%)
 create mode 100644 xmss_callbacks.h

diff --git a/Makefile b/Makefile
index d1b95d5..9f72e6d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,13 @@
 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
+# Alternate build settings to check for memory issues.
+#CC = clang
+#CFLAGS = -g -fsanitize=memory -Wall -Wextra -Wpedantic
 
-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 hash_address.c randombytes.c wots.c xmss.c xmss_core.c xmss_commons.c utils.c
+HEADERS = params.h thash.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 +87,24 @@ 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
+	-$(RM) xmss_verify_lib.a
diff --git a/fips202.c b/fips202.c
index 5e36d66..4565782 100644
--- a/fips202.c
+++ b/fips202.c
@@ -62,7 +62,7 @@ static const uint64_t KeccakF_RoundConstants[NROUNDS] =
     (uint64_t)0x8000000080008008ULL
 };
 
-void KeccakF1600_StatePermute(uint64_t * state)
+static void KeccakF1600_StatePermute(uint64_t * state)
 {
     int round;
 
diff --git a/hash_address.c b/hash_address.c
index 3a02473..5396796 100644
--- a/hash_address.c
+++ b/hash_address.c
@@ -1,5 +1,7 @@
 #include <stdint.h>
 
+#include "hash_address.h"
+
 void set_layer_addr(uint32_t addr[8], uint32_t layer)
 {
     addr[0] = layer;
diff --git a/params.h b/params.h
index 58c0619..c55ebaf 100644
--- a/params.h
+++ b/params.h
@@ -3,6 +3,21 @@
 
 #include <stdint.h>
 
+/* Compile-time constants, assuming SHA256 parameter sets only.
+ *
+ * See params.c for how WOTS_SIG_BYTES and releated were calculated.
+ *
+ * These are to facilitate integration with embedded targets
+ * where variable-length arrays cannot be used (e.g. wolfBoot).
+ * */
+#define XMSS_SHA256_N                   32
+#define XMSS_SHA256_PADDING_LEN         32
+#define XMSS_SHA256_MSG_PREFIX_LEN   (3 * XMSS_SHA256_N + XMSS_SHA256_PADDING_LEN)
+#define XMSS_SHA256_MAX_MSG_LEN        128
+#define XMSS_SHA256_MAX_MSG_HASH_LEN (XMSS_SHA256_MSG_PREFIX_LEN + XMSS_SHA256_MAX_MSG_LEN)
+#define XMSS_SHA256_WOTS_SIG_BYTES    2144
+#define XMSS_SHA256_WOTS_LEN            67
+
 /* These are merely internal identifiers for the supported hash functions. */
 #define XMSS_SHA2 0
 #define XMSS_SHAKE128 1
diff --git a/patch_readme.md b/patch_readme.md
new file mode 100644
index 0000000..a870353
--- /dev/null
+++ b/patch_readme.md
@@ -0,0 +1,42 @@
+# Addendum readme for the wolfssl xmss-reference integration patch
+
+This patch contains a number of changes that were primarily motivated to
+facilitate wolfBoot XMSS support for embedded-targets. Specifically, the
+following changes have been made:
+
+- All variable-length arrays (VLAs) necessary have been guarded with the define
+  `WOLFBOOT_SIGN_XMSS`, and replaced with static compile-time constant arrays,
+  with constants such as `XMSS_SHA256_WOTS_LEN` that have been defined in `params.h`.
+  They assume that the choice of SHA256 as the hashing function is a compile
+  time constant, and the function `core_hash()` has been updated to reflect this.
+  The param parsing logic in `params.c` has not been touched though, to allow for
+  in the future changing the underlying hash function at compile time if desired.
+- The signing and verifying APIs (`xmss_sign()`, `xmssmt_sign()`,`xmss_sign_open()`,
+  `xmssmt_sign_open()`) have been updated so that the message and signature are
+  passed as separate args, rather than a concatenated array. Additionally, for
+  wolfBoot builds the message length has been restricted to the compile time
+  constant of `XMSS_SHA256_MAX_MSG_LEN`. The appropriate APIs have had their
+  comments updates, and include an additional comment explaining this:
+```
+ * Note: in WOLFBOOT_SIGN_XMSS build, the max allowed message length (msglen)
+ * is XMSS_SHA256_MAX_MSG_LEN. This is to facilitate having a manageable small
+ * static array, rather than a variable length array, for the message hash.
+```
+- SHA256 and RNG operations are handled by registered callback functions. See
+  the header `xmss_callbacks.h` for the callback setter functions. This allows
+  offloading of SHA and RNG operations to wolfCrypt.
+- The tree-hash sources `hash.c` and `hash.h` were renamed to `thash.[c,h]`, to
+  avoid potential confusion with similarly named targets in wolfBoot.
+- The `Makefile` has been updated to build static libraries `xmss_lib.a`,
+  and `xmss_verify_lib.a`. The `xmss_verify_lib.a` is a verify-only build,
+  with an additional define `XMSS_VERIFY_ONLY` that guards out keygen
+  and signing functions.
+- The `Makefile` has been updated to link against wolfSSL `LDLIBS = -lwolfssl`
+  for the building of the tests in `test/`. The linking is *not* done for
+  building the static libs though, to avoid a circular dependency. Linking with
+  wolfssl to build the static libs is not necessary because the RNG and SHA
+  operations are provided by setting callbacks.
+- The tests in `test/` have been updated to reflect these changes.
+- Some minor changes were made to fix warnings from clang `-fsanitize=memory`.
+- Some minor cosmetic changes were made (cleanup trailing space, wrap long lines,
+  etc).
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 <fcntl.h>
 #include <unistd.h>
 
+#include "randombytes.h"
+
 static int fd = -1;
 
 void randombytes(unsigned char *x, unsigned long long xlen)
diff --git a/test/oid.c b/test/oid.c
index 6c51032..5daf5d1 100644
--- a/test/oid.c
+++ b/test/oid.c
@@ -22,7 +22,7 @@
         return -1;\
     }
 
-int main()
+int main(void)
 {
     uint32_t oid;
     xmss_params params;
diff --git a/test/speed.c b/test/speed.c
index 6ae58b0..80758ec 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 <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/random.h>
+
 #define XMSS_MLEN 32
 
 #ifndef XMSS_SIGNATURES
@@ -34,6 +39,12 @@
     #endif
 #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;
+
 static unsigned long long cpucycles(void)
 {
   unsigned long long result;
@@ -78,7 +89,7 @@ static void print_results(unsigned long long *t, size_t tlen)
   printf("\n");
 }
 
-int main()
+int main(void)
 {
     /* Make stdout buffer more responsive. */
     setbuf(stdout, NULL);
@@ -88,6 +99,24 @@ int main()
     int ret = 0;
     int i;
 
+    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 +130,16 @@ 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 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,15 +157,17 @@ 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);
 
     printf("Verifying %d signatures..\n", XMSS_SIGNATURES);
 
     for (i = 0; i < XMSS_SIGNATURES; i++) {
+        unsigned long long msglen = XMSS_MLEN;
+
         t[i] = cpucycles();
-        ret |= XMSS_SIGN_OPEN(mout, &mlen, sm, smlen, pk);
+        ret |= XMSS_SIGN_OPEN(msg, &msglen, sig, siglen, pk);
     }
     print_results(t, XMSS_SIGNATURES);
 
@@ -150,10 +179,58 @@ 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(t);
 
     return ret;
-}
\ No newline at end of file
+}
+
+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/vectors.c b/test/vectors.c
index f21ed6a..f5f5547 100644
--- a/test/vectors.c
+++ b/test/vectors.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Generate intermediate test vectors useful to test implementations.
  */
 
@@ -111,7 +111,7 @@ void vectors_wots(uint32_t oid) {
     printf("\n");
 }
 
-int main() {
+int main(void) {
     for (uint32_t oid = 1; oid <= 0x15; oid += 3) {
         vectors_wots(oid);
     }
diff --git a/test/wots.c b/test/wots.c
index 8b2b6de..fdaf369 100644
--- a/test/wots.c
+++ b/test/wots.c
@@ -3,14 +3,26 @@
 #include <string.h>
 
 #include "../wots.h"
+#include "../xmss_callbacks.h"
 #include "../randombytes.h"
 #include "../params.h"
 
-int main()
+#include <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/random.h>
+
+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(void)
 {
     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(&params, 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..a71a46a 100644
--- a/test/xmss.c
+++ b/test/xmss.c
@@ -4,9 +4,14 @@
 #include <stdlib.h>
 
 #include "../xmss.h"
+#include "../xmss_callbacks.h"
 #include "../params.h"
 #include "../randombytes.h"
 
+#include <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/random.h>
+
 #define XMSS_MLEN 32
 
 #ifndef XMSS_SIGNATURES
@@ -29,7 +34,13 @@
     #define XMSS_VARIANT "XMSS-SHA2_10_256"
 #endif
 
-int main()
+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(void)
 {
     xmss_params params;
     uint32_t oid;
@@ -42,34 +53,55 @@ 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);
+
+    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);
 
     printf("Testing %d %s signatures.. \n", XMSS_SIGNATURES, XMSS_VARIANT);
 
     for (i = 0; i < XMSS_SIGNATURES; i++) {
+        unsigned long long siglen = params.sig_bytes;
+        unsigned long long msglen = XMSS_MLEN;
+
         printf("  - iteration #%d:\n", i);
 
-        XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN);
+        if (XMSS_SIGN(sk, sig, &siglen, msg, XMSS_MLEN)) {
+            printf("  sign failed!\n");
+            ret = -1;
+        }
 
-        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 +110,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)) {
+        msg[0] ^= 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;
+        msg[0] ^= 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); 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)) {
             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..1984f1e 100644
--- a/test/xmss_determinism.c
+++ b/test/xmss_determinism.c
@@ -3,17 +3,47 @@
 #include <string.h>
 
 #include "../params.h"
+#include "../xmss_callbacks.h"
 #include "../xmss.h"
 #include "../randombytes.h"
 
+#include <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/random.h>
+
 #define MLEN 32
 
-int main()
+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(void)
 {
     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.. ");
 
@@ -24,10 +54,10 @@ int main()
     unsigned char sk[XMSS_OID_LEN + params.sk_bytes];
     unsigned char sk2[XMSS_OID_LEN + params.sk_bytes];
 
-    unsigned char m[MLEN];
-    unsigned char sm[params.sig_bytes + MLEN];
-    unsigned char sm2[params.sig_bytes + MLEN];
-    unsigned long long smlen;
+    unsigned char msg[MLEN];
+    unsigned char sig[params.sig_bytes];
+    unsigned char sig2[params.sig_bytes];
+    unsigned long long siglen = params.sig_bytes;
 
     xmss_keypair(pk, sk, oid);
 
@@ -35,16 +65,16 @@ int main()
     memcpy(sk2, sk, XMSS_OID_LEN + params.sk_bytes);
 
     /* Sign a random message (but twice the same one). */
-    randombytes(m, MLEN);
+    randombytes(msg, MLEN);
 
-    xmss_sign(sk, sm, &smlen, m, MLEN);
-    xmss_sign(sk2, sm2, &smlen, m, MLEN);
+    xmss_sign(sk, sig, &siglen, msg, MLEN);
+    xmss_sign(sk2, sig2, &siglen, msg, MLEN);
 
     /* Compare signature, and, if applicable, print the differences. */
-    if (memcmp(sm, sm2, params.sig_bytes + MLEN)) {
+    if (memcmp(sig, sig2, params.sig_bytes)) {
         fprintf(stderr, "signatures differ!\n");
         for (i = 0; i < params.sig_bytes + MLEN; i++) {
-            fprintf(stderr, (sm[i] != sm2[i] ? "x" : "."));
+            fprintf(stderr, (sig[i] != sig2[i] ? "x" : "."));
         }
         fprintf(stderr, "\n");
         return -1;
@@ -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..be145b5 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 <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/random.h>
+
 #define XMSS_MLEN 32
 
 // #ifndef XMSS_SIGNATURES
@@ -32,7 +37,13 @@
     #define XMSS_SIGNATURES (1 << 10)
 #endif
 
-int main()
+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(void)
 {
     xmss_params params;
     uint32_t oid;
@@ -46,14 +57,31 @@ 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 char *msg = malloc(XMSS_MLEN);
+    unsigned char *sig = malloc(params.sig_bytes);
+    unsigned long long siglen = params.sig_bytes;
     unsigned long long idx;
     unsigned long long j;
 
-    randombytes(m, XMSS_MLEN);
+    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(msg, XMSS_MLEN);
 
     XMSS_KEYPAIR(pk, sk, oid);
 
@@ -63,7 +91,7 @@ int main()
         if( (i & 1023) == 0)
             printf("  - iteration #%d:\n", i);
 
-        return_code = XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN);
+        return_code = XMSS_SIGN(sk, sig, &siglen, msg, XMSS_MLEN);
 
         if (return_code != 0) {
             printf("  Error! Return code was %d\n",return_code);
@@ -75,7 +103,7 @@ int main()
     for (; i < (XMSS_SIGNATURES) + 2; i++) {
         printf("  - iteration #%d:\n", i);
 
-        return_code = XMSS_SIGN(sk, sm, &smlen, m, XMSS_MLEN);
+        return_code = XMSS_SIGN(sk, sig, &siglen, msg, XMSS_MLEN);
 
         if (return_code == 0) {
                 printf("  Error! Return code was %d\n",return_code);
@@ -84,19 +112,65 @@ int main()
         else {
                 printf("Return code as expected [%d].\n", return_code);
         }
-        
+
         idx = (unsigned long)bytes_to_ull(sk, params.index_bytes);
         printf("Index: %llu\n", idx);
         printf("Secret key: %llu\n", idx);
         for (j = 0; j < XMSS_OID_LEN + params.sk_bytes;j++)
                 printf("%d ", sk[j]);
-        
+
         printf("\n");
     }
-    
-    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/hash.c b/thash.c
similarity index 82%
rename from hash.c
rename to thash.c
index 6724d43..eb01946 100644
--- a/hash.c
+++ b/thash.c
@@ -1,12 +1,14 @@
 #include <stdint.h>
+#include <stdio.h>
 #include <string.h>
-#include <openssl/sha.h>
 
+#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,39 @@ 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;
 
-    if (params->n == 24 && params->func == XMSS_SHA2) {
-        SHA256(in, inlen, buf);
-        memcpy(out, buf, 24);
-    }
-    else if (params->n == 24 && params->func == XMSS_SHAKE256) {
-        shake256(out, 24, in, inlen);
-    }   
-    else if (params->n == 32 && params->func == XMSS_SHA2) {
-        SHA256(in, inlen, out);
-    }
-    else if (params->n == 32 && params->func == XMSS_SHAKE128) {
-        shake128(out, 32, in, inlen);
-    }
-    else if (params->n == 32 && params->func == XMSS_SHAKE256) {
-        shake256(out, 32, in, inlen);
-    }
-    else if (params->n == 64 && params->func == XMSS_SHA2) {
-        SHA512(in, inlen, out);
+    if (sha_cb == NULL) {
+        return -1;
     }
-    else if (params->n == 64 && params->func == XMSS_SHAKE256) {
-        shake256(out, 64, in, inlen);
+
+    if (params == NULL || out == NULL || in == NULL) {
+        return -1;
     }
-    else {
+
+    /* 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 (ret != 0) { return ret; }
     return 0;
 }
 
@@ -63,7 +67,11 @@ int prf(const xmss_params *params,
         unsigned char *out, const unsigned char in[32],
         const unsigned char *key)
 {
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char buf[XMSS_SHA256_PADDING_LEN + XMSS_SHA256_N + 32];
+#else
     unsigned char buf[params->padding_len + params->n + 32];
+#endif
 
     ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF);
     memcpy(buf + params->padding_len, key, params->n);
@@ -80,7 +88,11 @@ int prf_keygen(const xmss_params *params,
         unsigned char *out, const unsigned char *in,
         const unsigned char *key)
 {
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char buf[XMSS_SHA256_PADDING_LEN + 2 * XMSS_SHA256_N + 32];
+#else
     unsigned char buf[params->padding_len + 2*params->n + 32];
+#endif
 
     ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF_KEYGEN);
     memcpy(buf + params->padding_len, key, params->n);
@@ -118,8 +130,13 @@ int thash_h(const xmss_params *params,
             unsigned char *out, const unsigned char *in,
             const unsigned char *pub_seed, uint32_t addr[8])
 {
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char buf[XMSS_SHA256_PADDING_LEN + 3 * XMSS_SHA256_N];
+    unsigned char bitmask[2 * XMSS_SHA256_N];
+#else
     unsigned char buf[params->padding_len + 3 * params->n];
     unsigned char bitmask[2 * params->n];
+#endif
     unsigned char addr_as_bytes[32];
     unsigned int i;
 
@@ -150,8 +167,13 @@ int thash_f(const xmss_params *params,
             unsigned char *out, const unsigned char *in,
             const unsigned char *pub_seed, uint32_t addr[8])
 {
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char buf[XMSS_SHA256_PADDING_LEN + 2 * XMSS_SHA256_N];
+    unsigned char bitmask[XMSS_SHA256_N];
+#else
     unsigned char buf[params->padding_len + 2 * params->n];
     unsigned char bitmask[params->n];
+#endif
     unsigned char addr_as_bytes[32];
     unsigned int i;
 
diff --git a/hash.h b/thash.h
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 <stdint.h>
 #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 <wolfssl/options.h>
+#include <wolfssl/wolfcrypt/sha256.h>
+#include <wolfssl/wolfcrypt/random.h>
 
 #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(&params, oid);
     if (parse_oid_result != 0) {
diff --git a/wots.c b/wots.c
index d9c8449..844940c 100644
--- a/wots.c
+++ b/wots.c
@@ -2,7 +2,7 @@
 #include <string.h>
 
 #include "utils.h"
-#include "hash.h"
+#include "thash.h"
 #include "wots.h"
 #include "hash_address.h"
 #include "params.h"
@@ -12,11 +12,15 @@
  * Expands an n-byte array into a len*n byte array using the `prf_keygen` function.
  */
 static void expand_seed(const xmss_params *params,
-                        unsigned char *outseeds, const unsigned char *inseed, 
+                        unsigned char *outseeds, const unsigned char *inseed,
                         const unsigned char *pub_seed, uint32_t addr[8])
 {
     uint32_t i;
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char buf[XMSS_SHA256_N + 32];
+#else
     unsigned char buf[params->n + 32];
+#endif
 
     set_hash_addr(addr, 0);
     set_key_and_mask(addr, 0);
@@ -83,7 +87,23 @@ static void wots_checksum(const xmss_params *params,
                           int *csum_base_w, const int *msg_base_w)
 {
     int csum = 0;
+#if defined WOLFBOOT_SIGN_XMSS
+    /* See params.c
+     *
+     * For NIST SP 800-208 parm sets with SHA256, we have:
+     *
+     *   params->wots_w     == 16
+     *   params->wots_log_w ==  4
+     *   params->wots_len2  ==  3
+     *
+     * Therefore:
+     *
+     *   (3 * 4 + 7) / 8 = 2
+     * */
+    unsigned char csum_bytes[2];
+#else
     unsigned char csum_bytes[(params->wots_len2 * params->wots_log_w + 7) / 8];
+#endif
     unsigned int i;
 
     /* Compute checksum. */
@@ -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));
-    ull_to_bytes(csum_bytes, sizeof(csum_bytes), csum);
+    ull_to_bytes(csum_bytes, (unsigned int) sizeof(csum_bytes), csum);
     base_w(params, csum_base_w, params->wots_len2, csum_bytes);
 }
 
@@ -139,7 +159,8 @@ void wots_sign(const xmss_params *params,
                const unsigned char *seed, const unsigned char *pub_seed,
                uint32_t addr[8])
 {
-    int lengths[params->wots_len];
+ /* int lengths[params->wots_len]; */
+    int lengths[67];
     uint32_t i;
 
     chain_lengths(params, lengths, msg);
@@ -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])
 {
+#if defined WOLFBOOT_SIGN_XMSS
+    int lengths[XMSS_SHA256_WOTS_LEN];
+#else
     int lengths[params->wots_len];
+#endif
     uint32_t i;
 
     chain_lengths(params, lengths, msg);
diff --git a/xmss.c b/xmss.c
index 9030f6e..b5f5168 100644
--- a/xmss.c
+++ b/xmss.c
@@ -1,5 +1,6 @@
 #include <stdint.h>
 
+#include "xmss.h"
 #include "params.h"
 #include "xmss_core.h"
 
@@ -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. */
 
+#ifndef XMSS_VERIFY_ONLY
 int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
 {
     xmss_params params;
@@ -26,8 +28,8 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
 }
 
 int xmss_sign(unsigned char *sk,
-              unsigned char *sm, unsigned long long *smlen,
-              const unsigned char *m, unsigned long long mlen)
+              unsigned char *sig, unsigned long long *siglen,
+              const unsigned char *msg, unsigned long long msglen)
 {
     xmss_params params;
     uint32_t oid = 0;
@@ -39,24 +41,7 @@ int xmss_sign(unsigned char *sk,
     if (xmss_parse_oid(&params, oid)) {
         return -1;
     }
-    return xmss_core_sign(&params, sk + XMSS_OID_LEN, sm, smlen, m, mlen);
-}
-
-int xmss_sign_open(unsigned char *m, unsigned long long *mlen,
-                   const unsigned char *sm, unsigned long long smlen,
-                   const unsigned char *pk)
-{
-    xmss_params params;
-    uint32_t oid = 0;
-    unsigned int i;
-
-    for (i = 0; i < XMSS_OID_LEN; i++) {
-        oid |= pk[XMSS_OID_LEN - i - 1] << (i * 8);
-    }
-    if (xmss_parse_oid(&params, oid)) {
-        return -1;
-    }
-    return xmss_core_sign_open(&params, m, mlen, sm, smlen, pk + XMSS_OID_LEN);
+    return xmss_core_sign(&params, sk + XMSS_OID_LEN, sig, siglen, msg, msglen);
 }
 
 int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
@@ -90,9 +75,27 @@ int xmssmt_sign(unsigned char *sk,
     }
     return xmssmt_core_sign(&params, sk + XMSS_OID_LEN, sm, smlen, m, mlen);
 }
+#endif /* ifndef XMSS_VERIFY_ONLY */
+
+int xmss_sign_open(const unsigned char *msg, unsigned long long *msglen,
+                   const unsigned char *sig, unsigned long long siglen,
+                   const unsigned char *pk)
+{
+    xmss_params params;
+    uint32_t oid = 0;
+    unsigned int i;
+
+    for (i = 0; i < XMSS_OID_LEN; i++) {
+        oid |= pk[XMSS_OID_LEN - i - 1] << (i * 8);
+    }
+    if (xmss_parse_oid(&params, oid)) {
+        return -1;
+    }
+    return xmss_core_sign_open(&params, msg, msglen, sig, siglen, pk + XMSS_OID_LEN);
+}
 
-int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen,
-                     const unsigned char *sm, unsigned long long smlen,
+int xmssmt_sign_open(const unsigned char *msg, unsigned long long *msglen,
+                     const unsigned char *sig, unsigned long long siglen,
                      const unsigned char *pk)
 {
     xmss_params params;
@@ -105,5 +108,5 @@ int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen,
     if (xmssmt_parse_oid(&params, oid)) {
         return -1;
     }
-    return xmssmt_core_sign_open(&params, m, mlen, sm, smlen, pk + XMSS_OID_LEN);
+    return xmssmt_core_sign_open(&params, msg, msglen, sig, siglen, pk + XMSS_OID_LEN);
 }
diff --git a/xmss.h b/xmss.h
index c7b4b69..b2b3980 100644
--- a/xmss.h
+++ b/xmss.h
@@ -3,6 +3,7 @@
 
 #include <stdint.h>
 
+#ifndef XMSS_VERIFY_ONLY
 /**
  * Generates a XMSS key pair for a given parameter set.
  * Format sk: [OID || (32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
@@ -13,23 +14,12 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);
 /**
  * Signs a message using an XMSS secret key.
  * Returns
- * 1. an array containing the signature followed by the message AND
+ * 1. an array containing the signature AND
  * 2. an updated secret key!
  */
 int xmss_sign(unsigned char *sk,
-              unsigned char *sm, unsigned long long *smlen,
-              const unsigned char *m, unsigned long long mlen);
-
-/**
- * Verifies a given message signature pair using a given public key.
- *
- * Note: m and mlen are pure outputs which carry the message in case
- * verification succeeds. The (input) message is assumed to be contained in sm
- * which has the form [signature || message].
- */
-int xmss_sign_open(unsigned char *m, unsigned long long *mlen,
-                   const unsigned char *sm, unsigned long long smlen,
-                   const unsigned char *pk);
+              unsigned char *sig, unsigned long long *siglen,
+              const unsigned char *msg, unsigned long long msglen);
 
 /*
  * Generates a XMSSMT key pair for a given parameter set.
@@ -41,21 +31,33 @@ int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid);
 /**
  * Signs a message using an XMSSMT secret key.
  * Returns
- * 1. an array containing the signature followed by the message AND
+ * 1. an array containing the signature AND
  * 2. an updated secret key!
  */
 int xmssmt_sign(unsigned char *sk,
-                unsigned char *sm, unsigned long long *smlen,
-                const unsigned char *m, unsigned long long mlen);
+                unsigned char *sig, unsigned long long *siglen,
+                const unsigned char *msg, unsigned long long msglen);
+#endif /* ifndef XMSS_VERIFY_ONLY */
+
+/**
+ * Verifies a given signature using a given public key.
+ *
+ * - msg is the input message of length msglen.
+ * - sig is the signature to verify, of length siglen.
+ * - pk is the public key without an OID.
+ */
+int xmss_sign_open(const unsigned char *msg, unsigned long long *msglen,
+                   const unsigned char *sig, unsigned long long siglen,
+                   const unsigned char *pk);
 
 /**
- * Verifies a given message signature pair using a given public key.
+ * Verifies a given signature using a given public key.
  *
- * Note: m and mlen are pure outputs which carry the message in case
- * verification succeeds. The (input) message is assumed to be contained in sm
- * which has the form [signature || message].
+ * - msg is the input message of length msglen.
+ * - sig is the signature to verify, of length siglen.
+ * - pk is the public key without an OID.
  */
-int xmssmt_sign_open(unsigned char *m, unsigned long long *mlen,
-                     const unsigned char *sm, unsigned long long smlen,
+int xmssmt_sign_open(const unsigned char *msg, unsigned long long *msglen,
+                     const unsigned char *sig, unsigned long long siglen,
                      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
+++ b/xmss_commons.c
@@ -2,7 +2,7 @@
 #include <string.h>
 #include <stdint.h>
 
-#include "hash.h"
+#include "thash.h"
 #include "hash_address.h"
 #include "params.h"
 #include "wots.h"
@@ -57,7 +57,11 @@ static void compute_root(const xmss_params *params, unsigned char *root,
                          const unsigned char *pub_seed, uint32_t addr[8])
 {
     uint32_t i;
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char buffer[2 * XMSS_SHA256_N];
+#else
     unsigned char buffer[2*params->n];
+#endif
 
     /* If leafidx is odd (last bit = 1), current path element is a right child
        and auth_path has to go left. Otherwise it is the other way around. */
@@ -74,7 +78,7 @@ static void compute_root(const xmss_params *params, unsigned char *root,
     for (i = 0; i < params->tree_height - 1; i++) {
         set_tree_height(addr, i);
         leafidx >>= 1;
-        set_tree_index(addr, leafidx);
+        set_tree_index(addr, (uint32_t) leafidx);
 
         /* Pick the right or left neighbor, depending on parity of the node. */
         if (leafidx & 1) {
@@ -91,7 +95,7 @@ static void compute_root(const xmss_params *params, unsigned char *root,
     /* The last iteration is exceptional; we do not copy an auth_path node. */
     set_tree_height(addr, params->tree_height - 1);
     leafidx >>= 1;
-    set_tree_index(addr, leafidx);
+    set_tree_index(addr, (uint32_t) leafidx);
     thash_h(params, root, buffer, pub_seed, addr);
 }
 
@@ -105,7 +109,11 @@ void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
                    const unsigned char *sk_seed, const unsigned char *pub_seed,
                    uint32_t ltree_addr[8], uint32_t ots_addr[8])
 {
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char pk[XMSS_SHA256_WOTS_SIG_BYTES];
+#else
     unsigned char pk[params->wots_sig_bytes];
+#endif
 
     wots_pkgen(params, pk, sk_seed, pub_seed, ots_addr);
 
@@ -118,31 +126,43 @@ void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
  * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  */
 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 *msg, unsigned long long *msglen,
+                        const unsigned char *sig, unsigned long long siglen,
                         const unsigned char *pk)
 {
     /* XMSS signatures are fundamentally an instance of XMSSMT signatures.
        For d=1, as is the case with XMSS, some of the calls in the XMSSMT
        routine become vacuous (i.e. the loop only iterates once, and address
        management can be simplified a bit).*/
-    return xmssmt_core_sign_open(params, m, mlen, sm, smlen, pk);
+    return xmssmt_core_sign_open(params, msg, msglen, sig, siglen, pk);
 }
 
 /**
  * Verifies a given message signature pair under a given public key.
  * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
+ *
+ * Note: in WOLFBOOT_SIGN_XMSS build, the max allowed message length (msglen)
+ * is XMSS_SHA256_MAX_MSG_LEN. This is to facilitate having a manageable small
+ * static array, rather than a variable length array, for the message hash.
  */
 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 *msg, unsigned long long *msglen,
+                          const unsigned char *sig, unsigned long long siglen,
                           const unsigned char *pk)
 {
     const unsigned char *pub_root = pk;
     const unsigned char *pub_seed = pk + params->n;
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char m_with_prefix[XMSS_SHA256_MAX_MSG_HASH_LEN];
+    unsigned char wots_pk[XMSS_SHA256_WOTS_SIG_BYTES];
+    unsigned char leaf[XMSS_SHA256_N];
+    unsigned char root[XMSS_SHA256_N];
+#else
+    unsigned char m_with_prefix[*msglen + params->padding_len + 3*params->n];
     unsigned char wots_pk[params->wots_sig_bytes];
     unsigned char leaf[params->n];
     unsigned char root[params->n];
+#endif
     unsigned char *mhash = root;
     unsigned long long idx = 0;
     unsigned int i;
@@ -152,24 +172,33 @@ int xmssmt_core_sign_open(const xmss_params *params,
     uint32_t ltree_addr[8] = {0};
     uint32_t node_addr[8] = {0};
 
+#if defined WOLFBOOT_SIGN_XMSS
+    if (*msglen > XMSS_SHA256_MAX_MSG_LEN) {
+        return -1;
+    }
+#endif
+
+    if (siglen != params->sig_bytes) {
+        /* Some inconsistency has happened. */
+        return -1;
+    }
+
     set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
     set_type(ltree_addr, XMSS_ADDR_TYPE_LTREE);
     set_type(node_addr, XMSS_ADDR_TYPE_HASHTREE);
 
-    *mlen = smlen - params->sig_bytes;
-
     /* Convert the index bytes from the signature to an integer. */
-    idx = bytes_to_ull(sm, params->index_bytes);
+    idx = bytes_to_ull(sig, params->index_bytes);
 
     /* Put the message all the way at the end of the m buffer, so that we can
      * prepend the required other inputs for the hash function. */
-    memcpy(m + params->sig_bytes, sm + params->sig_bytes, *mlen);
+    memset(m_with_prefix, 0, sizeof(m_with_prefix));
+    memcpy(m_with_prefix + params->padding_len + 3*params->n, msg, *msglen);
 
     /* Compute the message hash. */
-    hash_message(params, mhash, sm + params->index_bytes, pk, idx,
-                 m + params->sig_bytes - params->padding_len - 3*params->n,
-                 *mlen);
-    sm += params->index_bytes + params->n;
+    hash_message(params, mhash, sig + params->index_bytes, pk, idx,
+                 m_with_prefix, *msglen);
+    sig += params->index_bytes + params->n;
 
     /* For each subtree.. */
     for (i = 0; i < params->d; i++) {
@@ -188,28 +217,24 @@ int xmssmt_core_sign_open(const xmss_params *params,
         set_ots_addr(ots_addr, idx_leaf);
         /* Initially, root = mhash, but on subsequent iterations it is the root
            of the subtree below the currently processed subtree. */
-        wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
-        sm += params->wots_sig_bytes;
+        wots_pk_from_sig(params, wots_pk, sig, root, pub_seed, ots_addr);
+        sig += params->wots_sig_bytes;
 
         /* Compute the leaf node using the WOTS public key. */
         set_ltree_addr(ltree_addr, idx_leaf);
         l_tree(params, leaf, wots_pk, pub_seed, ltree_addr);
 
         /* Compute the root node of this subtree. */
-        compute_root(params, root, leaf, idx_leaf, sm, pub_seed, node_addr);
-        sm += params->tree_height*params->n;
+        compute_root(params, root, leaf, idx_leaf, sig, pub_seed, node_addr);
+        sig += params->tree_height*params->n;
     }
 
     /* Check if the root node equals the root node in the public key. */
     if (memcmp(root, pub_root, params->n)) {
-        /* If not, zero the message */
-        memset(m, 0, *mlen);
-        *mlen = 0;
+        /* If not, set message length to zero */
+        *msglen = 0;
         return -1;
     }
 
-    /* If verification was successful, copy the message from the signature. */
-    memcpy(m, sm, *mlen);
-
     return 0;
 }
diff --git a/xmss_commons.h b/xmss_commons.h
index 9d9f077..33dbffe 100644
--- a/xmss_commons.h
+++ b/xmss_commons.h
@@ -18,7 +18,7 @@ void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
  * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  */
 int xmss_core_sign_open(const xmss_params *params,
-                        unsigned char *m, unsigned long long *mlen,
+                        const unsigned char *msg, unsigned long long *msglen,
                         const unsigned char *sm, unsigned long long smlen,
                         const unsigned char *pk);
 
@@ -27,7 +27,7 @@ int xmss_core_sign_open(const xmss_params *params,
  * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  */
 int xmssmt_core_sign_open(const xmss_params *params,
-                          unsigned char *m, unsigned long long *mlen,
+                          const unsigned char *msg, unsigned long long *msglen,
                           const unsigned char *sm, unsigned long long smlen,
                           const unsigned char *pk);
 #endif
diff --git a/xmss_core.c b/xmss_core.c
index af9f8d1..7e76564 100644
--- a/xmss_core.c
+++ b/xmss_core.c
@@ -2,15 +2,47 @@
 #include <string.h>
 #include <stdint.h>
 
-#include "hash.h"
+#include "thash.h"
 #include "hash_address.h"
 #include "params.h"
-#include "randombytes.h"
 #include "wots.h"
 #include "utils.h"
 #include "xmss_commons.h"
 #include "xmss_core.h"
 
+#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.
@@ -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,
 }
 
 /**
- * Signs a message. Returns an array containing the signature followed by the
- * message and an updated secret key.
+ * Signs a message. Returns an array containing the signature,
+ * and an updated secret key.
  */
 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)
+                   unsigned char *sig, unsigned long long *siglen,
+                   const unsigned char *msg, unsigned long long msglen)
 {
     /* XMSS signatures are fundamentally an instance of XMSSMT signatures.
        For d=1, as is the case with XMSS, some of the calls in the XMSSMT
        routine become vacuous (i.e. the loop only iterates once, and address
        management can be simplified a bit).*/
-    return xmssmt_core_sign(params, sk, sm, smlen, m, mlen);
+    return xmssmt_core_sign(params, sk, sig, siglen, msg, msglen);
 }
 
 /*
@@ -169,21 +205,35 @@ 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 = rng_cb(seed, sizeof(seed));
+
+    if (ret != 0) {
+        return -1;
+    }
 
-    randombytes(seed, 3 * params->n);
     xmssmt_core_seed_keypair(params, pk, sk, seed);
 
     return 0;
 }
 
+
 /**
- * Signs a message. Returns an array containing the signature followed by the
- * message and an updated secret key.
+ * Signs a message.
+ * Returns
+ * 1. an array containing the signature AND
+ * 2. an updated secret key!
+ *
+ * Note: in WOLFBOOT_SIGN_XMSS build, the max allowed message length (msglen)
+ * is XMSS_SHA256_MAX_MSG_LEN. This is to facilitate having a manageable small
+ * static array, rather than a variable length array, for the message hash.
  */
 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)
+                     unsigned char *sig, unsigned long long *siglen,
+                     const unsigned char *msg, unsigned long long msglen)
 {
     const unsigned char *sk_seed = sk + params->index_bytes;
     const unsigned char *sk_prf = sk + params->index_bytes + params->n;
@@ -197,28 +247,45 @@ int xmssmt_core_sign(const xmss_params *params,
     unsigned int i;
     uint32_t idx_leaf;
 
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char m_with_prefix[XMSS_SHA256_MAX_MSG_HASH_LEN];
+#else
+    unsigned char m_with_prefix[msglen + params->padding_len + 3*params->n];
+#endif
+
+#if defined WOLFBOOT_SIGN_XMSS
+    if (msglen > XMSS_SHA256_MAX_MSG_LEN) {
+        return -1;
+    }
+#endif
+
+    if (*siglen != params->sig_bytes) {
+        /* Some inconsistency has happened. */
+        return -1;
+    }
+
     uint32_t ots_addr[8] = {0};
     set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
 
     /* Already put the message in the right place, to make it easier to prepend
      * things when computing the hash over the message. */
-    memcpy(sm + params->sig_bytes, m, mlen);
-    *smlen = params->sig_bytes + mlen;
+    memset(m_with_prefix, 0, sizeof(m_with_prefix));
+    memcpy(m_with_prefix + params->padding_len + 3*params->n, msg, msglen);
 
     /* Read and use the current index from the secret key. */
     idx = (unsigned long)bytes_to_ull(sk, params->index_bytes);
-    
+
     /* Check if we can still sign with this sk.
      * If not, return -2
-     * 
-     * If this is the last possible signature (because the max index value 
-     * is reached), production implementations should delete the secret key 
+     *
+     * If this is the last possible signature (because the max index value
+     * is reached), production implementations should delete the secret key
      * to prevent accidental further use.
-     * 
-     * For the case of total tree height of 64 we do not use the last signature 
-     * to be on the safe side (there is no index value left to indicate that the 
+     *
+     * For the case of total tree height of 64 we do not use the last signature
+     * to be on the safe side (there is no index value left to indicate that the
      * key is finished, hence external handling would be necessary)
-     */ 
+     */
     if (idx >= ((1ULL << params->full_height) - 1)) {
         // Delete secret key here. We only do this in memory, production code
         // has to make sure that this happens on disk.
@@ -226,11 +293,11 @@ int xmssmt_core_sign(const xmss_params *params,
         memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes));
         if (idx > ((1ULL << params->full_height) - 1))
             return -2; // We already used all one-time keys
-        if ((params->full_height == 64) && (idx == ((1ULL << params->full_height) - 1))) 
+        if ((params->full_height == 64) && (idx == ((1ULL << params->full_height) - 1)))
                 return -2; // We already used all one-time keys
     }
-    
-    memcpy(sm, sk, params->index_bytes);
+
+    memcpy(sig, sk, params->index_bytes);
 
     /*************************************************************************
      * THIS IS WHERE PRODUCTION IMPLEMENTATIONS WOULD UPDATE THE SECRET KEY. *
@@ -240,13 +307,12 @@ int xmssmt_core_sign(const xmss_params *params,
 
     /* Compute the digest randomization value. */
     ull_to_bytes(idx_bytes_32, 32, idx);
-    prf(params, sm + params->index_bytes, idx_bytes_32, sk_prf);
+    prf(params, sig + params->index_bytes, idx_bytes_32, sk_prf);
 
     /* Compute the message hash. */
-    hash_message(params, mhash, sm + params->index_bytes, pub_root, idx,
-                 sm + params->sig_bytes - params->padding_len - 3*params->n,
-                 mlen);
-    sm += params->index_bytes + params->n;
+    hash_message(params, mhash, sig + params->index_bytes, pub_root, idx,
+                 m_with_prefix, msglen);
+    sig += params->index_bytes + params->n;
 
     set_type(ots_addr, XMSS_ADDR_TYPE_OTS);
 
@@ -261,13 +327,14 @@ int xmssmt_core_sign(const xmss_params *params,
         /* Compute a WOTS signature. */
         /* Initially, root = mhash, but on subsequent iterations it is the root
            of the subtree below the currently processed subtree. */
-        wots_sign(params, sm, root, sk_seed, pub_seed, ots_addr);
-        sm += params->wots_sig_bytes;
+        wots_sign(params, sig, root, sk_seed, pub_seed, ots_addr);
+        sig += params->wots_sig_bytes;
 
         /* Compute the authentication path for the used WOTS leaf. */
-        treehash(params, root, sm, sk_seed, pub_seed, idx_leaf, ots_addr);
-        sm += params->tree_height*params->n;
+        treehash(params, root, sig, sk_seed, pub_seed, idx_leaf, ots_addr);
+        sig += params->tree_height*params->n;
     }
 
     return 0;
 }
+#endif /* ifndef XMSS_VERIFY_ONLY */
diff --git a/xmss_core.h b/xmss_core.h
index e83bc7d..21d72ef 100644
--- a/xmss_core.h
+++ b/xmss_core.h
@@ -12,6 +12,7 @@
  */
 unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params);
 
+#ifndef XMSS_VERIFY_ONLY
 /*
  * Generates a XMSS key pair for a given parameter set.
  * Format sk: [(32bit) index || SK_SEED || SK_PRF || PUB_SEED || root]
@@ -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);
 
-/**
- * Verifies a given message signature pair under a given public key.
- * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
- */
-int xmss_core_sign_open(const xmss_params *params,
-                        unsigned char *m, unsigned long long *mlen,
-                        const unsigned char *sm, unsigned long long smlen,
-                        const unsigned char *pk);
-
 /*
  * Generates a XMSSMT key pair for a given parameter set.
  * Format sk: [(ceil(h/8) bit) index || SK_SEED || SK_PRF || PUB_SEED || root]
@@ -64,13 +56,23 @@ 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);
+#endif /* ifndef XMSS_VERIFY_ONLY */
+
+/**
+ * Verifies a given message signature pair under a given public key.
+ * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
+ */
+int xmss_core_sign_open(const xmss_params *params,
+                        const unsigned char *msg, unsigned long long *msglen,
+                        const unsigned char *sm, unsigned long long smlen,
+                        const unsigned char *pk);
 
 /**
  * Verifies a given message signature pair under a given public key.
  * Note that this assumes a pk without an OID, i.e. [root || PUB_SEED]
  */
 int xmssmt_core_sign_open(const xmss_params *params,
-                          unsigned char *m, unsigned long long *mlen,
+                          const unsigned char *msg, unsigned long long *msglen,
                           const unsigned char *sm, unsigned long long smlen,
                           const unsigned char *pk);
 
diff --git a/xmss_core_fast.c b/xmss_core_fast.c
index cbf87ec..0a31323 100644
--- a/xmss_core_fast.c
+++ b/xmss_core_fast.c
@@ -2,15 +2,19 @@
 #include <string.h>
 #include <stdint.h>
 
-#include "hash.h"
+#include "thash.h"
 #include "hash_address.h"
 #include "params.h"
-#include "randombytes.h"
 #include "wots.h"
 #include "utils.h"
 #include "xmss_commons.h"
 #include "xmss_core.h"
 
+#ifndef XMSS_VERIFY_ONLY
+#include "xmss_callbacks.h"
+
+static rng_cb_t rng_cb = NULL;
+
 typedef struct{
     unsigned char h;
     unsigned long next_idx;
@@ -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;
 
-        states[i].stackoffset = bytes_to_ull(sk, 4);
+        states[i].stackoffset = (unsigned int) bytes_to_ull(sk, 4);
         sk += 4;
 
         states[i].stacklevels = sk;
@@ -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;
 
-        states[i].next_leaf = bytes_to_ull(sk, 4);
+        states[i].next_leaf = (unsigned int) bytes_to_ull(sk, 4);
         sk += 4;
     }
 
@@ -299,8 +312,8 @@ static void treehash_update(const xmss_params *params,
     copy_subtree_addr(node_addr, addr);
     set_type(node_addr, 2);
 
-    set_ltree_addr(ltree_addr, treehash->next_idx);
-    set_ots_addr(ots_addr, treehash->next_idx);
+    set_ltree_addr(ltree_addr, (uint32_t) treehash->next_idx);
+    set_ots_addr(ots_addr, (uint32_t) treehash->next_idx);
 
     unsigned char nodebuffer[2 * params->n];
     unsigned int nodeheight = 0;
@@ -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);
-        set_tree_index(node_addr, (treehash->next_idx >> (nodeheight+1)));
+        set_tree_index(node_addr, (uint32_t) (treehash->next_idx >> (nodeheight+1)));
         thash_h(params, nodebuffer, nodebuffer, pub_seed, node_addr);
         nodeheight++;
         treehash->stackusage--;
@@ -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) {
-        set_ltree_addr(ltree_addr, leaf_idx);
-        set_ots_addr(ots_addr, leaf_idx);
+        set_ltree_addr(ltree_addr, (uint32_t) leaf_idx);
+        set_ots_addr(ots_addr, (uint32_t) leaf_idx);
         gen_leaf_wots(params, state->auth, sk_seed, pub_seed, ltree_addr, ots_addr);
     }
     else {
         set_tree_height(node_addr, (tau-1));
-        set_tree_index(node_addr, leaf_idx >> tau);
+        set_tree_index(node_addr, (uint32_t) leaf_idx >> tau);
         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 +503,13 @@ static void bds_round(const xmss_params *params,
             }
             else {
                 offset = (1 << (params->tree_height - 1 - i)) + i - params->tree_height;
-                rowidx = ((leaf_idx >> i) - 1) >> 1;
+                rowidx = (unsigned int) ((leaf_idx >> i) - 1) >> 1;
                 memcpy(state->auth + i * params->n, state->retain + (offset + rowidx) * params->n, params->n);
             }
         }
 
         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 = (unsigned int) leaf_idx + 1 + 3 * (1 << i);
             if (startidx < 1U << params->tree_height) {
                 state->treehash[i].h = i;
                 state->treehash[i].next_idx = startidx;
@@ -507,6 +520,8 @@ static void bds_round(const xmss_params *params,
     }
 }
 
+#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
@@ -530,6 +545,7 @@ unsigned long long xmss_xmssmt_core_sk_bytes(const xmss_params *params)
         + (params->d - 1) * params->wots_sig_bytes;
 }
 
+#ifndef XMSS_VERIFY_ONLY
 /*
  * Generates a XMSS key pair for a given parameter set.
  * Format sk: [(32bit) idx || SK_SEED || SK_PRF || root || PUB_SEED]
@@ -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 +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 = 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 = 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);
 
     // Compute root
-    treehash_init(params, pk, params->tree_height, 0, &state, sk + params->index_bytes, sk + params->index_bytes + 3*params->n, addr);
+    treehash_init(params, pk, params->tree_height, 0, &state,
+                  sk + params->index_bytes,
+                  sk + params->index_bytes + 3*params->n, addr);
+
     // copy root to sk
     memcpy(sk + params->index_bytes + 2*params->n, pk, params->n);
 
@@ -577,19 +609,39 @@ int xmss_core_keypair(const xmss_params *params,
 /**
  * Signs a message.
  * Returns
- * 1. an array containing the signature followed by the message AND
+ * 1. an array containing the signature AND
  * 2. an updated secret key!
  *
+ * Note: in WOLFBOOT_SIGN_XMSS build, the max allowed message length (msglen)
+ * is XMSS_SHA256_MAX_MSG_LEN. This is to facilitate having a manageable small
+ * static array, rather than a variable length array, for the message hash.
  */
 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)
+                   unsigned char *sig, unsigned long long *siglen,
+                   const unsigned char *msg, unsigned long long msglen)
 {
     const unsigned char *pub_root = sk + params->index_bytes + 2*params->n;
 
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char m_with_prefix[XMSS_SHA256_MAX_MSG_HASH_LEN];
+#else
+    unsigned char m_with_prefix[msglen + params->padding_len + 3*params->n];
+#endif
+
     uint16_t i = 0;
 
+#if defined WOLFBOOT_SIGN_XMSS
+    if (msglen > XMSS_SHA256_MAX_MSG_LEN) {
+        return -1;
+    }
+#endif
+
+    if (*siglen != params->sig_bytes) {
+        /* Some inconsistency has happened. */
+        return -1;
+    }
+
     // TODO refactor BDS state not to need separate treehash instances
     bds_state state;
     treehash_inst treehash[params->tree_height - params->bds_k];
@@ -599,19 +651,21 @@ int xmss_core_sign(const xmss_params *params,
     xmss_deserialize_state(params, &state, 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];
+
     /* Check if we can still sign with this sk.
      * If not, return -2
-     * 
-     * If this is the last possible signature (because the max index value 
-     * is reached), production implementations should delete the secret key 
+     *
+     * If this is the last possible signature (because the max index value
+     * is reached), production implementations should delete the secret key
      * to prevent accidental further use.
-     * 
-     * For the case of total tree height of 64 we do not use the last signature 
-     * to be on the safe side (there is no index value left to indicate that the 
+     *
+     * For the case of total tree height of 64 we do not use the last signature
+     * to be on the safe side (there is no index value left to indicate that the
      * key is finished, hence external handling would be necessary)
-     */ 
+     */
     if (idx >= ((1ULL << params->full_height) - 1)) {
         // Delete secret key here. We only do this in memory, production code
         // has to make sure that this happens on disk.
@@ -619,10 +673,10 @@ int xmss_core_sign(const xmss_params *params,
         memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes));
         if (idx > ((1ULL << params->full_height) - 1))
             return -2; // We already used all one-time keys
-        if ((params->full_height == 64) && (idx == ((1ULL << params->full_height) - 1))) 
+        if ((params->full_height == 64) && (idx == ((1ULL << params->full_height) - 1)))
                 return -2; // We already used all one-time keys
     }
-    
+
     unsigned char sk_seed[params->n];
     memcpy(sk_seed, sk + params->index_bytes, params->n);
     unsigned char sk_prf[params->n];
@@ -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. */
-    memcpy(sm + params->sig_bytes, m, mlen);
+    memset(m_with_prefix, 0, sizeof(m_with_prefix));
+    memcpy(m_with_prefix + params->padding_len + 3*params->n, msg, msglen);
 
     /* Compute the message hash. */
     hash_message(params, msg_h, R, pub_root, idx,
-                 sm + params->sig_bytes - params->padding_len - 3*params->n,
-                 mlen);
+                 m_with_prefix, msglen);
 
     // Start collecting signature
-    *smlen = 0;
+    *siglen = 0;
 
     // Copy index to signature
-    sm[0] = (idx >> 24) & 255;
-    sm[1] = (idx >> 16) & 255;
-    sm[2] = (idx >> 8) & 255;
-    sm[3] = idx & 255;
+    sig[0] = (idx >> 24) & 255;
+    sig[1] = (idx >> 16) & 255;
+    sig[2] = (idx >> 8) & 255;
+    sig[3] = idx & 255;
 
-    sm += 4;
-    *smlen += 4;
+    sig += 4;
+    *siglen += 4;
 
     // Copy R to signature
     for (i = 0; i < params->n; i++) {
-        sm[i] = R[i];
+        sig[i] = R[i];
     }
 
-    sm += params->n;
-    *smlen += params->n;
+    sig += params->n;
+    *siglen += params->n;
 
     // ----------------------------------
     // Now we start to "really sign"
@@ -691,27 +745,24 @@ int xmss_core_sign(const xmss_params *params,
 
     // Prepare Address
     set_type(ots_addr, 0);
-    set_ots_addr(ots_addr, idx);
+    set_ots_addr(ots_addr, (uint32_t) idx);
 
     // Compute WOTS signature
-    wots_sign(params, sm, msg_h, sk_seed, pub_seed, ots_addr);
+    wots_sign(params, sig, msg_h, sk_seed, pub_seed, ots_addr);
 
-    sm += params->wots_sig_bytes;
-    *smlen += params->wots_sig_bytes;
+    sig += params->wots_sig_bytes;
+    *siglen += params->wots_sig_bytes;
 
     // the auth path was already computed during the previous round
-    memcpy(sm, state.auth, params->tree_height*params->n);
+    memcpy(sig, state.auth, params->tree_height*params->n);
 
     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 += params->tree_height*params->n;
-    *smlen += params->tree_height*params->n;
-
-    memcpy(sm, m, mlen);
-    *smlen += mlen;
+    sig += params->tree_height*params->n;
+    *siglen += params->tree_height*params->n;
 
     /* Write the updated BDS state back into sk. */
     xmss_serialize_state(params, sk, &state);
@@ -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)
 {
-    uint32_t addr[8] = {0};
-    unsigned int i;
-    unsigned char *wots_sigs;
+    uint32_t        addr[8] = {0};
+    unsigned int    i;
+    unsigned char * wots_sigs;
+    int             ret = 0;
 
     // TODO refactor BDS state not to need separate treehash instances
     bds_state states[2*params->d - 1];
@@ -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 = 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 = 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 +839,37 @@ int xmssmt_core_keypair(const xmss_params *params,
 /**
  * Signs a message.
  * Returns
- * 1. an array containing the signature followed by the message AND
+ * 1. an array containing the signature AND
  * 2. an updated secret key!
  *
+ * Note: in WOLFBOOT_SIGN_XMSS build, the max allowed message length (msglen)
+ * is XMSS_SHA256_MAX_MSG_LEN. This is to facilitate having a manageable small
+ * static array, rather than a variable length array, for the message hash.
  */
 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)
+                     unsigned char *sig, unsigned long long *siglen,
+                     const unsigned char *msg, unsigned long long msglen)
 {
     const unsigned char *pub_root = sk + params->index_bytes + 2*params->n;
 
+#if defined WOLFBOOT_SIGN_XMSS
+    unsigned char m_with_prefix[XMSS_SHA256_MAX_MSG_HASH_LEN];
+#else
+    unsigned char m_with_prefix[msglen + params->padding_len + 3*params->n];
+#endif
+
+#if defined WOLFBOOT_SIGN_XMSS
+    if (msglen > XMSS_SHA256_MAX_MSG_LEN) {
+        return -1;
+    }
+#endif
+
+    if (*siglen != params->sig_bytes) {
+        /* Some inconsistency has happened. */
+        return -1;
+    }
+
     uint64_t idx_tree;
     uint32_t idx_leaf;
     uint64_t i, j;
@@ -824,15 +905,15 @@ int xmssmt_core_sign(const xmss_params *params,
 
     /* Check if we can still sign with this sk.
      * If not, return -2
-     * 
-     * If this is the last possible signature (because the max index value 
-     * is reached), production implementations should delete the secret key 
+     *
+     * If this is the last possible signature (because the max index value
+     * is reached), production implementations should delete the secret key
      * to prevent accidental further use.
-     * 
-     * For the case of total tree height of 64 we do not use the last signature 
-     * to be on the safe side (there is no index value left to indicate that the 
+     *
+     * For the case of total tree height of 64 we do not use the last signature
+     * to be on the safe side (there is no index value left to indicate that the
      * key is finished, hence external handling would be necessary)
-     */ 
+     */
     if (idx >= ((1ULL << params->full_height) - 1)) {
         // Delete secret key here. We only do this in memory, production code
         // has to make sure that this happens on disk.
@@ -840,10 +921,10 @@ int xmssmt_core_sign(const xmss_params *params,
         memset(sk + params->index_bytes, 0, (params->sk_bytes - params->index_bytes));
         if (idx > ((1ULL << params->full_height) - 1))
             return -2; // We already used all one-time keys
-        if ((params->full_height == 64) && (idx == ((1ULL << params->full_height) - 1))) 
+        if ((params->full_height == 64) && (idx == ((1ULL << params->full_height) - 1)))
                 return -2; // We already used all one-time keys
     }
-    
+
     memcpy(sk_seed, sk+params->index_bytes, params->n);
     memcpy(sk_prf, sk+params->index_bytes+params->n, params->n);
     memcpy(pub_seed, sk+params->index_bytes+3*params->n, params->n);
@@ -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. */
-    memcpy(sm + params->sig_bytes, m, mlen);
+    memset(m_with_prefix, 0, sizeof(m_with_prefix));
+    memcpy(m_with_prefix + params->padding_len + 3*params->n, msg, msglen);
+
 
     /* Compute the message hash. */
     hash_message(params, msg_h, R, pub_root, idx,
-                 sm + params->sig_bytes - params->padding_len - 3*params->n,
-                 mlen);
+                 m_with_prefix,
+              /* sig + params->sig_bytes - params->padding_len - 3*params->n, */
+                 msglen);
 
     // Start collecting signature
-    *smlen = 0;
+    *siglen = 0;
 
     // Copy index to signature
     for (i = 0; i < params->index_bytes; i++) {
-        sm[i] = (idx >> 8*(params->index_bytes - 1 - i)) & 255;
+        sig[i] = (idx >> 8*(params->index_bytes - 1 - i)) & 255;
     }
 
-    sm += params->index_bytes;
-    *smlen += params->index_bytes;
+    sig += params->index_bytes;
+    *siglen += params->index_bytes;
 
     // Copy R to signature
     for (i = 0; i < params->n; i++) {
-        sm[i] = R[i];
+        sig[i] = R[i];
     }
 
-    sm += params->n;
-    *smlen += params->n;
+    sig += params->n;
+    *siglen += params->n;
 
     // ----------------------------------
     // Now we start to "really sign"
@@ -908,27 +992,27 @@ int xmssmt_core_sign(const xmss_params *params,
     set_ots_addr(ots_addr, idx_leaf);
 
     // Compute WOTS signature
-    wots_sign(params, sm, msg_h, sk_seed, pub_seed, ots_addr);
+    wots_sign(params, sig, msg_h, sk_seed, pub_seed, ots_addr);
 
-    sm += params->wots_sig_bytes;
-    *smlen += params->wots_sig_bytes;
+    sig += params->wots_sig_bytes;
+    *siglen += params->wots_sig_bytes;
 
-    memcpy(sm, states[0].auth, params->tree_height*params->n);
-    sm += params->tree_height*params->n;
-    *smlen += params->tree_height*params->n;
+    memcpy(sig, states[0].auth, params->tree_height*params->n);
+    sig += params->tree_height*params->n;
+    *siglen += params->tree_height*params->n;
 
     // prepare signature of remaining layers
     for (i = 1; i < params->d; i++) {
         // put WOTS signature in place
-        memcpy(sm, wots_sigs + (i-1)*params->wots_sig_bytes, params->wots_sig_bytes);
+        memcpy(sig, wots_sigs + (i-1)*params->wots_sig_bytes, params->wots_sig_bytes);
 
-        sm += params->wots_sig_bytes;
-        *smlen += params->wots_sig_bytes;
+        sig += params->wots_sig_bytes;
+        *siglen += params->wots_sig_bytes;
 
         // put AUTH nodes in place
-        memcpy(sm, states[i].auth, params->tree_height*params->n);
-        sm += params->tree_height*params->n;
-        *smlen += params->tree_height*params->n;
+        memcpy(sig, states[i].auth, params->tree_height*params->n);
+        sig += params->tree_height*params->n;
+        *siglen += params->tree_height*params->n;
     }
 
     updates = (params->tree_height - params->bds_k) >> 1;
@@ -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)));
-            set_layer_addr(addr, i);
+            set_layer_addr(addr, (uint32_t) i);
             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 +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);
 
-            set_layer_addr(ots_addr, (i+1));
+            set_layer_addr(ots_addr, (uint32_t) (i+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)));
 
@@ -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
-            needswap_upto = i;
+            needswap_upto = (int) i;
             for (j = 0; j < params->tree_height-params->bds_k; j++) {
                 states[i].treehash[j].completed = 1;
             }
         }
     }
 
-    memcpy(sm, m, mlen);
-    *smlen += mlen;
-
     xmssmt_serialize_state(params, sk, states);
 
     return 0;
 }
+#endif /* ifndef XMSS_VERIFY_ONLY */
-- 
2.40.0

