summaryrefslogtreecommitdiff
path: root/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean
diff options
context:
space:
mode:
Diffstat (limited to 'lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean')
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/Makefile49
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c78
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h50
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h81
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/config.mk17
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c161
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h32
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h31
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c106
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h30
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/manifest.mn29
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h53
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/pqclean_sphincs-shake256-192f-simple_clean.gyp45
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c356
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h28
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c74
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c199
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h64
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c167
-rw-r--r--lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h41
20 files changed, 1691 insertions, 0 deletions
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/Makefile b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/Makefile
new file mode 100644
index 000000000..fe090f3ff
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+USE_GCOV =
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+WARNING_CFLAGS = $(NULL)
+
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c
new file mode 100644
index 000000000..cce899fe7
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.c
@@ -0,0 +1,78 @@
+#include <stdint.h>
+
+#include "address.h"
+#include "params.h"
+#include "utils.h"
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes(
+ unsigned char *bytes, const uint32_t addr[8]) {
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes(
+ bytes + i * 4, 4, addr[i]);
+ }
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(
+ uint32_t addr[8], uint32_t layer) {
+ addr[0] = layer;
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(
+ uint32_t addr[8], uint64_t tree) {
+ addr[1] = 0;
+ addr[2] = (uint32_t) (tree >> 32);
+ addr[3] = (uint32_t) tree;
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ uint32_t addr[8], uint32_t type) {
+ addr[4] = type;
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr(
+ uint32_t out[8], const uint32_t in[8]) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+/* These functions are used for OTS addresses. */
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ uint32_t addr[8], uint32_t keypair) {
+ addr[5] = keypair;
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ uint32_t out[8], const uint32_t in[8]) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+ out[5] = in[5];
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(
+ uint32_t addr[8], uint32_t chain) {
+ addr[6] = chain;
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr(
+ uint32_t addr[8], uint32_t hash) {
+ addr[7] = hash;
+}
+
+/* These functions are used for all hash tree addresses (including FORS). */
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(
+ uint32_t addr[8], uint32_t tree_height) {
+ addr[6] = tree_height;
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ uint32_t addr[8], uint32_t tree_index) {
+ addr[7] = tree_index;
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h
new file mode 100644
index 000000000..f57ffb75f
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/address.h
@@ -0,0 +1,50 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDRESS_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDRESS_H
+
+#include <stdint.h>
+
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS 0
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK 1
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE 2
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE 3
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK 4
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes(
+ unsigned char *bytes, const uint32_t addr[8]);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(
+ uint32_t addr[8], uint32_t layer);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(
+ uint32_t addr[8], uint64_t tree);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ uint32_t addr[8], uint32_t type);
+
+/* Copies the layer and tree part of one address into the other */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr(
+ uint32_t out[8], const uint32_t in[8]);
+
+/* These functions are used for WOTS and FORS addresses. */
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ uint32_t addr[8], uint32_t keypair);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(
+ uint32_t addr[8], uint32_t chain);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr(
+ uint32_t addr[8], uint32_t hash);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ uint32_t out[8], const uint32_t in[8]);
+
+/* These functions are used for all hash tree addresses (including FORS). */
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(
+ uint32_t addr[8], uint32_t tree_height);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ uint32_t addr[8], uint32_t tree_index);
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h
new file mode 100644
index 000000000..48e622dba
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/api.h
@@ -0,0 +1,81 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_API_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_API_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+
+
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+"
+
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 96
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 48
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_BYTES 35664
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 72
+
+
+/*
+ * Returns the length of a secret key, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void);
+
+/*
+ * Returns the length of a public key, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void);
+
+/*
+ * Returns the length of a signature, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_bytes(void);
+
+/*
+ * Returns the length of the seed required to generate a key pair, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seedbytes(void);
+
+/*
+ * Generates a SPHINCS+ key pair given a seed.
+ * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [root || PUB_SEED]
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seed_keypair(
+ uint8_t *pk, uint8_t *sk, const uint8_t *seed);
+
+/*
+ * Generates a SPHINCS+ key pair.
+ * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [root || PUB_SEED]
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair(
+ uint8_t *pk, uint8_t *sk);
+
+/**
+ * Returns an array containing a detached signature.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature(
+ uint8_t *sig, size_t *siglen,
+ const uint8_t *m, size_t mlen, const uint8_t *sk);
+
+/**
+ * Verifies a detached signature and message under a given public key.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify(
+ const uint8_t *sig, size_t siglen,
+ const uint8_t *m, size_t mlen, const uint8_t *pk);
+
+/**
+ * Returns an array containing the signature followed by the message.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign(
+ uint8_t *sm, size_t *smlen,
+ const uint8_t *m, size_t mlen, const uint8_t *sk);
+
+/**
+ * Verifies a given signature-message pair under a given public key.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_open(
+ uint8_t *m, size_t *mlen,
+ const uint8_t *sm, size_t smlen, const uint8_t *pk);
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/config.mk b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/config.mk
new file mode 100644
index 000000000..b28c9ce64
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/config.mk
@@ -0,0 +1,17 @@
+# DO NOT EDIT: generated from config.mk.subdirs.template
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# add fixes for platform integration issues here.
+#
+# liboqs programs expect the public include files to be in oqs/xxxx,
+# So we put liboqs in it's own module, oqs, and point to the dist files
+INCLUDES += -I$(CORE_DEPTH)/lib/liboqs/src/common/pqclean_shims -I$(CORE_DEPTH)/lib/liboqs/src/common/sha3/xkcp_low/KeccakP-1600/plain-64bits
+DEFINES +=
+
+ifeq ($(OS_ARCH), Darwin)
+DEFINES += -DOQS_HAVE_ALIGNED_ALLOC -DOQS_HAVE_MEMALIGN -DOQS_HAVE_POSIX_MEMALIGN
+endif
+
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c
new file mode 100644
index 000000000..bc6f7f50c
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.c
@@ -0,0 +1,161 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "address.h"
+#include "fors.h"
+#include "hash.h"
+#include "hash_state.h"
+#include "thash.h"
+#include "utils.h"
+
+static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
+ uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr(
+ sk, sk_seed, fors_leaf_addr, hash_state_seeded);
+}
+
+static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
+ const unsigned char *pub_seed,
+ uint32_t fors_leaf_addr[8],
+ const hash_state *hash_state_seeded) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1(
+ leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
+}
+
+static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
+ const unsigned char *pub_seed,
+ uint32_t addr_idx, const uint32_t fors_tree_addr[8],
+ const hash_state *hash_state_seeded) {
+ uint32_t fors_leaf_addr[8] = {0};
+
+ /* Only copy the parts that must be kept in fors_leaf_addr. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ fors_leaf_addr, fors_tree_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ fors_leaf_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ fors_leaf_addr, addr_idx);
+
+ fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
+ fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
+}
+
+/**
+ * Interprets m as PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT-bit unsigned integers.
+ * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits.
+ * Assumes indices has space for PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES integers.
+ */
+static void message_to_indices(uint32_t *indices, const unsigned char *m) {
+ unsigned int i, j;
+ unsigned int offset = 0;
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES; i++) {
+ indices[i] = 0;
+ for (j = 0; j < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT; j++) {
+ indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
+ offset++;
+ }
+ }
+}
+
+/**
+ * Signs a message m, deriving the secret key from sk_seed and the FTS address.
+ * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_sign(
+ unsigned char *sig, unsigned char *pk,
+ const unsigned char *m,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
+ uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES];
+ unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ uint32_t fors_tree_addr[8] = {0};
+ uint32_t fors_pk_addr[8] = {0};
+ uint32_t idx_offset;
+ unsigned int i;
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ fors_tree_addr, fors_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ fors_pk_addr, fors_addr);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK);
+
+ message_to_indices(indices, m);
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES; i++) {
+ idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(
+ fors_tree_addr, 0);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ fors_tree_addr, indices[i] + idx_offset);
+
+ /* Include the secret key part that produces the selected leaf node. */
+ fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ /* Compute the authentication path for this leaf node. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT(
+ roots + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sig, sk_seed, pub_seed,
+ indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
+ hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT;
+ }
+
+ /* Hash horizontally across all tree roots to derive the public key. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES(
+ pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
+}
+
+/**
+ * Derives the FORS public key from a signature.
+ * This can be used for verification by comparing to a known public key, or to
+ * subsequently verify a signature on the derived public key. The latter is the
+ * typical use-case when used as an FTS below an OTS in a hypertree.
+ * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_pk_from_sig(
+ unsigned char *pk,
+ const unsigned char *sig, const unsigned char *m,
+ const unsigned char *pub_seed, const uint32_t fors_addr[8],
+ const hash_state *hash_state_seeded) {
+ uint32_t indices[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES];
+ unsigned char roots[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ uint32_t fors_tree_addr[8] = {0};
+ uint32_t fors_pk_addr[8] = {0};
+ uint32_t idx_offset;
+ unsigned int i;
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(fors_tree_addr, fors_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(fors_pk_addr, fors_addr);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(fors_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(fors_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSPK);
+
+ message_to_indices(indices, m);
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES; i++) {
+ idx_offset = i * (1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(fors_tree_addr, 0);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(fors_tree_addr, indices[i] + idx_offset);
+
+ /* Derive the leaf from the included secret key part. */
+ fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ /* Derive the corresponding root node of this tree. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root(roots + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, leaf, indices[i], idx_offset, sig,
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT;
+ }
+
+ /* Hash horizontally across all tree roots to derive the public key. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES(pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h
new file mode 100644
index 000000000..a2648beab
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/fors.h
@@ -0,0 +1,32 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_H
+
+#include <stdint.h>
+
+#include "hash_state.h"
+#include "params.h"
+
+/**
+ * Signs a message m, deriving the secret key from sk_seed and the FTS address.
+ * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_sign(
+ unsigned char *sig, unsigned char *pk,
+ const unsigned char *m,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ const uint32_t fors_addr[8], const hash_state *hash_state_seeded);
+
+/**
+ * Derives the FORS public key from a signature.
+ * This can be used for verification by comparing to a known public key, or to
+ * subsequently verify a signature on the derived public key. The latter is the
+ * typical use-case when used as an FTS below an OTS in a hypertree.
+ * Assumes m contains at least PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES bits.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_pk_from_sig(
+ unsigned char *pk,
+ const unsigned char *sig, const unsigned char *m,
+ const unsigned char *pub_seed, const uint32_t fors_addr[8],
+ const hash_state *hash_state_seeded);
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h
new file mode 100644
index 000000000..bbd5ebdb3
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash.h
@@ -0,0 +1,31 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_HASH_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_HASH_H
+
+#include "hash_state.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function(
+ hash_state *hash_state_seeded,
+ const unsigned char *pub_seed, const unsigned char *sk_seed);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr(
+ unsigned char *out, const unsigned char *key, const uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_gen_message_random(
+ unsigned char *R,
+ const unsigned char *sk_prf, const unsigned char *optrand,
+ const unsigned char *m, size_t mlen,
+ const hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message(
+ unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
+ const unsigned char *R, const unsigned char *pk,
+ const unsigned char *m, size_t mlen,
+ const hash_state *hash_state_seeded);
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c
new file mode 100644
index 000000000..81d055a56
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_shake256.c
@@ -0,0 +1,106 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "address.h"
+#include "hash.h"
+#include "params.h"
+#include "utils.h"
+
+#include "fips202.h"
+
+/* For SHAKE256, there is no immediate reason to initialize at the start,
+ so this function is an empty operation. */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function(
+ hash_state *hash_state_seeded, // NOLINT(readability-non-const-parameter)
+ const unsigned char *pub_seed, const unsigned char *sk_seed) {
+ (void)hash_state_seeded; /* Suppress an 'unused parameter' warning. */
+ (void)pub_seed; /* Suppress an 'unused parameter' warning. */
+ (void)sk_seed; /* Suppress an 'unused parameter' warning. */
+}
+
+/* This is not necessary for SHAKE256, so we don't do anything */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(
+ hash_state *hash_state_seeded) { // NOLINT(readability-non-const-parameter)
+ (void)hash_state_seeded;
+}
+
+/*
+ * Computes PRF(key, addr), given a secret key of PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N bytes and an address
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr(
+ unsigned char *out, const unsigned char *key, const uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+ unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES];
+
+ memcpy(buf, key, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, addr);
+
+ shake256(out, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES);
+
+ (void)hash_state_seeded; /* Prevent unused parameter warning. */
+}
+
+/**
+ * Computes the message-dependent randomness R, using a secret seed and an
+ * optional randomization value as well as the message.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_gen_message_random(
+ unsigned char *R,
+ const unsigned char *sk_prf, const unsigned char *optrand,
+ const unsigned char *m, size_t mlen,
+ const hash_state *hash_state_seeded) {
+ shake256incctx state;
+
+ shake256_inc_init(&state);
+ shake256_inc_absorb(&state, sk_prf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ shake256_inc_absorb(&state, optrand, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ shake256_inc_absorb(&state, m, mlen);
+ shake256_inc_finalize(&state);
+ shake256_inc_squeeze(R, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, &state);
+ shake256_inc_ctx_release(&state);
+
+ (void)hash_state_seeded; /* Prevent unused parameter warning. */
+}
+
+/**
+ * Computes the message hash using R, the public key, and the message.
+ * Outputs the message digest and the index of the leaf. The index is split in
+ * the tree index and the leaf index, for convenient copying to an address.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message(
+ unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
+ const unsigned char *R, const unsigned char *pk,
+ const unsigned char *m, size_t mlen,
+ const hash_state *hash_state_seeded) {
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BITS (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D - 1))
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BITS + 7) / 8)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BITS PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BITS + 7) / 8)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_DGST_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BYTES)
+
+ unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_DGST_BYTES];
+ unsigned char *bufp = buf;
+ shake256incctx state;
+
+ shake256_inc_init(&state);
+ shake256_inc_absorb(&state, R, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ shake256_inc_absorb(&state, pk, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PK_BYTES);
+ shake256_inc_absorb(&state, m, mlen);
+ shake256_inc_finalize(&state);
+ shake256_inc_squeeze(buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_DGST_BYTES, &state);
+ shake256_inc_ctx_release(&state);
+
+ memcpy(digest, bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES);
+ bufp += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES;
+
+ *tree = PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull(
+ bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES);
+ *tree &= (~(uint64_t)0) >> (64 - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BITS);
+ bufp += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_BYTES;
+
+ *leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull(
+ bufp, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BYTES);
+ *leaf_idx &= (~(uint32_t)0) >> (32 - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_LEAF_BITS);
+
+ (void)hash_state_seeded; /* Prevent unused parameter warning. */
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h
new file mode 100644
index 000000000..7d92ef872
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/hash_state.h
@@ -0,0 +1,30 @@
+#ifndef SPX_HASH_STATE_H
+#define SPX_HASH_STATE_H
+
+/**
+ * Defines the type of the hash function state.
+ *
+ * Don't be fooled into thinking this instance of SPHINCS+ isn't stateless!
+ *
+ * From Section 7.2.2 from the SPHINCS+ round-2 specification:
+ *
+ * Each of the instances of the tweakable hash function take PK.seed as its
+ * first input, which is constant for a given key pair – and, thus, across
+ * a single signature. This leads to a lot of redundant computation. To remedy
+ * this, we pad PK.seed to the length of a full 64-byte SHA-256 input block.
+ * Because of the Merkle-Damgård construction that underlies SHA-256, this
+ * allows for reuse of the intermediate SHA-256 state after the initial call to
+ * the compression function which improves performance.
+ *
+ * We pass this hash state around in functions, because otherwise we need to
+ * have a global variable.
+ *
+ * SHAKE256 does not need this state. Because this implementation is generated
+ * from a shared code base, we still need to specify some hash_state as it is
+ * still passed around. We chose to use an `int` as a placeholder for this
+ * purpose.
+ */
+
+#define hash_state int
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/manifest.mn b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/manifest.mn
new file mode 100644
index 000000000..ec5a6c111
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/manifest.mn
@@ -0,0 +1,29 @@
+# DO NOT EDIT: generated from manifest.mn.subdirs.template
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../../../../../..
+
+MODULE = oqs
+
+LIBRARY_NAME = oqs_src_sig_sphincs_pqclean_sphincs-shake256-192f-simple_clean
+SHARED_LIBRARY = $(NULL)
+
+CSRCS = \
+ address.c \
+ fors.c \
+ hash_shake256.c \
+ sign.c \
+ thash_shake256_simple.c \
+ utils.c \
+ wots.c \
+ $(NULL)
+
+# only add module debugging in opt builds if DEBUG_PKCS11 is set
+ifdef DEBUG_PKCS11
+ DEFINES += -DDEBUG_MODULE
+endif
+
+# This part of the code, including all sub-dirs, can be optimized for size
+export ALLOW_OPT_CODE_SIZE = 1
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h
new file mode 100644
index 000000000..292f83c4d
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/params.h
@@ -0,0 +1,53 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PARAMS_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PARAMS_H
+
+/* Hash output length in bytes. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N 24
+/* Height of the hypertree. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FULL_HEIGHT 66
+/* Number of subtree layer. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D 22
+/* FORS tree dimensions. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT 8
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES 33
+/* Winternitz parameter, */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W 16
+
+/* The hash function is defined by linking a different hash.c file, as opposed
+ to setting a #define constant. */
+
+/* For clarity */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES 32
+
+/* WOTS parameters. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW 4
+
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1 (8 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N / PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW)
+
+/* PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 3
+
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1 + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES
+
+/* Subtree size. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FULL_HEIGHT / PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D)
+
+/* FORS parameters. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES + 7) / 8)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT + 1) * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_PK_BYTES PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N
+
+/* Resulting SPX sizes. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES +\
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FULL_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N)
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_SK_BYTES (2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_PK_BYTES)
+
+/* Optionally, signing can be made non-deterministic using optrand.
+ This can help counter side-channel attacks that would benefit from
+ getting a large number of traces when the signer uses the same nodes. */
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_OPTRAND_BYTES 32
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/pqclean_sphincs-shake256-192f-simple_clean.gyp b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/pqclean_sphincs-shake256-192f-simple_clean.gyp
new file mode 100644
index 000000000..058d520e7
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/pqclean_sphincs-shake256-192f-simple_clean.gyp
@@ -0,0 +1,45 @@
+# DO NOT EDIT: generated from subdir.gyp.template
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'oqs_src_sig_sphincs_pqclean_sphincs-shake256-192f-simple_clean',
+ 'type': 'static_library',
+ 'sources': [
+ 'address.c',
+ 'fors.c',
+ 'hash_shake256.c',
+ 'sign.c',
+ 'thash_shake256_simple.c',
+ 'utils.c',
+ 'wots.c',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ ],
+ 'include_dirs': [
+ '<(DEPTH)/lib/liboqs/src/common/pqclean_shims',
+ '<(DEPTH)/lib/liboqs/src/common/sha3/xkcp_low/KeccakP-1600/plain-64bits',
+ ],
+ [ 'OS=="mac"', {
+ 'defines': [
+ 'OQS_HAVE_POSIX_MEMALIGN',
+ 'OQS_HAVE_ALIGNED_ALLOC',
+ 'OQS_HAVE_MEMALIGN'
+ ]
+ }]
+ },
+ 'variables': {
+ 'module': 'oqs'
+ }
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c
new file mode 100644
index 000000000..7efb32f90
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/sign.c
@@ -0,0 +1,356 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "address.h"
+#include "api.h"
+#include "fors.h"
+#include "hash.h"
+#include "hash_state.h"
+#include "params.h"
+#include "randombytes.h"
+#include "thash.h"
+#include "utils.h"
+#include "wots.h"
+
+/**
+ * Computes the leaf at a given address. First generates the WOTS key pair,
+ * then computes leaf by hashing horizontally.
+ */
+static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
+ const unsigned char *pub_seed,
+ uint32_t addr_idx, const uint32_t tree_addr[8],
+ const hash_state *hash_state_seeded) {
+ unsigned char pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES];
+ uint32_t wots_addr[8] = {0};
+ uint32_t wots_pk_addr[8] = {0};
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr(
+ wots_addr, tree_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ wots_addr, addr_idx);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_gen_pk(
+ pk, sk_seed, pub_seed, wots_addr, hash_state_seeded);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ wots_pk_addr, wots_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN(
+ leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded);
+}
+
+/*
+ * Returns the length of a secret key, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) {
+ return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES;
+}
+
+/*
+ * Returns the length of a public key, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) {
+ return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES;
+}
+
+/*
+ * Returns the length of a signature, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_bytes(void) {
+ return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_BYTES;
+}
+
+/*
+ * Returns the length of the seed required to generate a key pair, in bytes
+ */
+size_t PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seedbytes(void) {
+ return PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES;
+}
+
+/*
+ * Generates an SPX key pair given a seed of length
+ * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [PUB_SEED || root]
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seed_keypair(
+ uint8_t *pk, uint8_t *sk, const uint8_t *seed) {
+ /* We do not need the auth path in key generation, but it simplifies the
+ code to have just one treehash routine that computes both root and path
+ in one function. */
+ unsigned char auth_path[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ uint32_t top_tree_addr[8] = {0};
+ hash_state hash_state_seeded;
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(
+ top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D - 1);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ top_tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE);
+
+ /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */
+ memcpy(sk, seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES);
+
+ memcpy(pk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+
+ /* This hook allows the hash function instantiation to do whatever
+ preparation or computation it needs, based on the public seed. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk);
+
+ /* Compute root node of the top-most subtree. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
+ sk + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, auth_path, sk, sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, 0, 0,
+ wots_gen_leaf, top_tree_addr, &hash_state_seeded);
+
+ memcpy(pk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sk + 3 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded);
+ return 0;
+}
+
+/*
+ * Generates an SPX key pair.
+ * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
+ * Format pk: [PUB_SEED || root]
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_keypair(
+ uint8_t *pk, uint8_t *sk) {
+ unsigned char seed[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES];
+ randombytes(seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_CRYPTO_SEEDBYTES);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_seed_keypair(
+ pk, sk, seed);
+
+ return 0;
+}
+
+/**
+ * Returns an array containing a detached signature.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature(
+ uint8_t *sig, size_t *siglen,
+ const uint8_t *m, size_t mlen, const uint8_t *sk) {
+ const unsigned char *sk_seed = sk;
+ const unsigned char *sk_prf = sk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+ const unsigned char *pk = sk + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+ const unsigned char *pub_seed = pk;
+
+ unsigned char optrand[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES];
+ unsigned char root[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ uint32_t i;
+ uint64_t tree;
+ uint32_t idx_leaf;
+ uint32_t wots_addr[8] = {0};
+ uint32_t tree_addr[8] = {0};
+
+ hash_state hash_state_seeded;
+
+ /* This hook allows the hash function instantiation to do whatever
+ preparation or computation it needs, based on the public seed. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function(
+ &hash_state_seeded,
+ pub_seed, sk_seed);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE);
+
+ /* Optionally, signing can be made non-deterministic using optrand.
+ This can help counter side-channel attacks that would benefit from
+ getting a large number of traces when the signer uses the same nodes. */
+ randombytes(optrand, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ /* Compute the digest randomization value. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_gen_message_random(
+ sig, sk_prf, optrand, m, mlen, &hash_state_seeded);
+
+ /* Derive the message digest and leaf index from R, PK and M. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message(
+ mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ wots_addr, idx_leaf);
+
+ /* Sign the message hash using FORS. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_sign(
+ sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES;
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr(
+ wots_addr, tree_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ wots_addr, idx_leaf);
+
+ /* Compute a WOTS signature. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_sign(
+ sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES;
+
+ /* Compute the authentication path for the used WOTS leaf. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
+ root, sig, sk_seed, pub_seed, idx_leaf, 0,
+ wots_gen_leaf, tree_addr, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ /* Update the indices for the next layer. */
+ idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT) - 1));
+ tree = tree >> PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT;
+ }
+
+ *siglen = PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES;
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded);
+ return 0;
+}
+
+/**
+ * Verifies a detached signature and message under a given public key.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify(
+ const uint8_t *sig, size_t siglen,
+ const uint8_t *m, size_t mlen, const uint8_t *pk) {
+ const unsigned char *pub_seed = pk;
+ const unsigned char *pub_root = pk + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+ unsigned char mhash[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_MSG_BYTES];
+ unsigned char wots_pk[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES];
+ unsigned char root[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ unsigned char leaf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ unsigned int i;
+ uint64_t tree;
+ uint32_t idx_leaf;
+ uint32_t wots_addr[8] = {0};
+ uint32_t tree_addr[8] = {0};
+ uint32_t wots_pk_addr[8] = {0};
+
+ hash_state hash_state_seeded;
+
+ if (siglen != PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES) {
+ return -1;
+ }
+
+ /* This hook allows the hash function instantiation to do whatever
+ preparation or computation it needs, based on the public seed. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_initialize_hash_function(
+ &hash_state_seeded,
+ pub_seed, NULL);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ wots_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTS);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ tree_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_type(
+ wots_pk_addr, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_WOTSPK);
+
+ /* Derive the message digest and leaf index from R || PK || M. */
+ /* The additional PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N is a result of the hash domain separator. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message(
+ mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ /* Layer correctly defaults to 0, so no need to set_layer_addr */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ wots_addr, idx_leaf);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_fors_pk_from_sig(
+ root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_BYTES;
+
+ /* For each subtree.. */
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_D; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_layer_addr(tree_addr, i);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_subtree_addr(
+ wots_addr, tree_addr);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_keypair_addr(
+ wots_addr, idx_leaf);
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_copy_keypair_addr(
+ wots_pk_addr, wots_addr);
+
+ /* The WOTS public key is only correct if the signature was correct. */
+ /* Initially, root is the FORS pk, but on subsequent iterations it is
+ the root of the subtree below the currently processed subtree. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_pk_from_sig(
+ wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_BYTES;
+
+ /* Compute the leaf node using the WOTS public key. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN(
+ leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded);
+
+ /* Compute the root node of this subtree. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root(
+ root, leaf, idx_leaf, 0, sig, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT,
+ pub_seed, tree_addr, &hash_state_seeded);
+ sig += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ /* Update the indices for the next layer. */
+ idx_leaf = (tree & ((1 << PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT) - 1));
+ tree = tree >> PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT;
+ }
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_destroy_hash_function(&hash_state_seeded);
+ /* Check if the root node equals the root node in the public key. */
+ if (memcmp(root, pub_root, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Returns an array containing the signature followed by the message.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign(
+ uint8_t *sm, size_t *smlen,
+ const uint8_t *m, size_t mlen, const uint8_t *sk) {
+ size_t siglen;
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_signature(
+ sm, &siglen, m, mlen, sk);
+
+ memmove(sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, m, mlen);
+ *smlen = siglen + mlen;
+
+ return 0;
+}
+
+/**
+ * Verifies a given signature-message pair under a given public key.
+ */
+int PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_open(
+ uint8_t *m, size_t *mlen,
+ const uint8_t *sm, size_t smlen, const uint8_t *pk) {
+ /* The API caller does not necessarily know what size a signature should be
+ but SPHINCS+ signatures are always exactly PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES. */
+ if (smlen < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES) {
+ memset(m, 0, smlen);
+ *mlen = 0;
+ return -1;
+ }
+
+ *mlen = smlen - PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES;
+
+ if (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_crypto_sign_verify(
+ sm, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, *mlen, pk)) {
+ memset(m, 0, smlen);
+ *mlen = 0;
+ return -1;
+ }
+
+ /* If verification was successful, move the message to the right place. */
+ memmove(m, sm + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_BYTES, *mlen);
+
+ return 0;
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h
new file mode 100644
index 000000000..b090f26a6
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash.h
@@ -0,0 +1,28 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_THASH_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_THASH_H
+
+#include "hash_state.h"
+
+#include <stdint.h>
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c
new file mode 100644
index 000000000..8ed51d81e
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/thash_shake256_simple.c
@@ -0,0 +1,74 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "address.h"
+#include "hash_state.h"
+#include "params.h"
+#include "thash.h"
+
+#include "fips202.h"
+
+/**
+ * Takes an array of inblocks concatenated arrays of PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N bytes.
+ */
+static void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash(
+ unsigned char *out, unsigned char *buf,
+ const unsigned char *in, unsigned int inblocks,
+ const unsigned char *pub_seed, uint32_t addr[8]) {
+
+ memcpy(buf, pub_seed, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_addr_to_bytes(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, addr);
+ memcpy(buf + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES, in, inblocks * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+
+ shake256(out, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, buf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + inblocks * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+}
+
+/* The wrappers below ensure that we use fixed-size buffers on the stack */
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+
+ unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + 1 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash(
+ out, buf, in, 1, pub_seed, addr);
+
+ (void)hash_state_seeded; /* Avoid unused parameter warning. */
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+
+ unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + 2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash(
+ out, buf, in, 2, pub_seed, addr);
+
+ (void)hash_state_seeded; /* Avoid unused parameter warning. */
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_WOTS_LEN(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+
+ unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash(
+ out, buf, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN, pub_seed, addr);
+
+ (void)hash_state_seeded; /* Avoid unused parameter warning. */
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_FORS_TREES(
+ unsigned char *out, const unsigned char *in,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+
+ unsigned char buf[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_BYTES + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash(
+ out, buf, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_TREES, pub_seed, addr);
+
+ (void)hash_state_seeded; /* Avoid unused parameter warning. */
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c
new file mode 100644
index 000000000..82ae4b3ff
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.c
@@ -0,0 +1,199 @@
+#include <stddef.h>
+#include <string.h>
+
+#include "address.h"
+#include "hash.h"
+#include "hash_state.h"
+#include "params.h"
+#include "thash.h"
+#include "utils.h"
+
+/**
+ * Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes(
+ unsigned char *out, size_t outlen, unsigned long long in) {
+
+ /* Iterate over out in decreasing order, for big-endianness. */
+ for (size_t i = outlen; i > 0; i--) {
+ out[i - 1] = in & 0xff;
+ in = in >> 8;
+ }
+}
+
+/**
+ * Converts the inlen bytes in 'in' from big-endian byte order to an integer.
+ */
+unsigned long long PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull(
+ const unsigned char *in, size_t inlen) {
+ unsigned long long retval = 0;
+
+ for (size_t i = 0; i < inlen; i++) {
+ retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i));
+ }
+ return retval;
+}
+
+/**
+ * Computes a root node given a leaf and an auth path.
+ * Expects address to be complete other than the tree_height and tree_index.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root(
+ unsigned char *root, const unsigned char *leaf,
+ uint32_t leaf_idx, uint32_t idx_offset,
+ const unsigned char *auth_path, uint32_t tree_height,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+ uint32_t i;
+ unsigned char buffer[2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+
+ /* If leaf_idx 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. */
+ if (leaf_idx & 1) {
+ memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, leaf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ } else {
+ memcpy(buffer, leaf, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ }
+ auth_path += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+
+ for (i = 0; i < tree_height - 1; i++) {
+ leaf_idx >>= 1;
+ idx_offset >>= 1;
+ /* Set the address of the node we're creating. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(addr, i + 1);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ addr, leaf_idx + idx_offset);
+
+ /* Pick the right or left neighbor, depending on parity of the node. */
+ if (leaf_idx & 1) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2(
+ buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, buffer, pub_seed, addr, hash_state_seeded);
+ memcpy(buffer, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ } else {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2(
+ buffer, buffer, pub_seed, addr, hash_state_seeded);
+ memcpy(buffer + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, auth_path, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ }
+ auth_path += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N;
+ }
+
+ /* The last iteration is exceptional; we do not copy an auth_path node. */
+ leaf_idx >>= 1;
+ idx_offset >>= 1;
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(addr, tree_height);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ addr, leaf_idx + idx_offset);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2(
+ root, buffer, pub_seed, addr, hash_state_seeded);
+}
+
+/**
+ * For a given leaf index, computes the authentication path and the resulting
+ * root node using Merkle's TreeHash algorithm.
+ * Expects the layer and tree parts of the tree_addr to be set, as well as the
+ * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE).
+ * Applies the offset idx_offset to indices before building addresses, so that
+ * it is possible to continue counting indices across trees.
+ */
+static void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash(
+ unsigned char *root, unsigned char *auth_path,
+ unsigned char *stack, unsigned int *heights,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height,
+ void (*gen_leaf)(
+ unsigned char * /* leaf */,
+ const unsigned char * /* sk_seed */,
+ const unsigned char * /* pub_seed */,
+ uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
+ const hash_state * /* hash_state_seeded */),
+ uint32_t tree_addr[8],
+ const hash_state *hash_state_seeded) {
+
+ unsigned int offset = 0;
+ uint32_t idx;
+ uint32_t tree_idx;
+
+ for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) {
+ /* Add the next leaf node to the stack. */
+ gen_leaf(stack + offset * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N,
+ sk_seed, pub_seed, idx + idx_offset, tree_addr,
+ hash_state_seeded);
+ offset++;
+ heights[offset - 1] = 0;
+
+ /* If this is a node we need for the auth path.. */
+ if ((leaf_idx ^ 0x1) == idx) {
+ memcpy(auth_path, stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ }
+
+ /* While the top-most nodes are of equal height.. */
+ while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
+ /* Compute index of the new node, in the next layer. */
+ tree_idx = (idx >> (heights[offset - 1] + 1));
+
+ /* Set the address of the node we're creating. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_height(
+ tree_addr, heights[offset - 1] + 1);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_tree_index(
+ tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1)));
+ /* Hash the top-most nodes from the stack together. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_2(
+ stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, stack + (offset - 2)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N,
+ pub_seed, tree_addr, hash_state_seeded);
+ offset--;
+ /* Note that the top-most node is now one layer higher. */
+ heights[offset - 1]++;
+
+ /* If this is a node we need for the auth path.. */
+ if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) {
+ memcpy(auth_path + heights[offset - 1]*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N,
+ stack + (offset - 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+ }
+ }
+ }
+ memcpy(root, stack, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+}
+
+/* The wrappers below ensure that we use fixed-size buffers on the stack */
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT(
+ unsigned char *root, unsigned char *auth_path,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t leaf_idx, uint32_t idx_offset,
+ void (*gen_leaf)(
+ unsigned char * /* leaf */,
+ const unsigned char * /* sk_seed */,
+ const unsigned char * /* pub_seed */,
+ uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
+ const hash_state * /* hash_state_seeded */),
+ uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
+
+ unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT + 1];
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash(
+ root, auth_path, stack, heights, sk_seed, pub_seed,
+ leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
+}
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
+ unsigned char *root, unsigned char *auth_path,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t leaf_idx, uint32_t idx_offset,
+ void (*gen_leaf)(
+ unsigned char * /* leaf */,
+ const unsigned char * /* sk_seed */,
+ const unsigned char * /* pub_seed */,
+ uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
+ const hash_state * /* hash_state_seeded */),
+ uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
+
+ unsigned char stack[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT + 1)*PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N];
+ unsigned int heights[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT + 1];
+
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash(
+ root, auth_path, stack, heights, sk_seed, pub_seed,
+ leaf_idx, idx_offset, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h
new file mode 100644
index 000000000..66b280a35
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/utils.h
@@ -0,0 +1,64 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_UTILS_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_UTILS_H
+
+#include "hash_state.h"
+#include "params.h"
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes(
+ unsigned char *out, size_t outlen, unsigned long long in);
+
+/**
+ * Converts the inlen bytes in 'in' from big-endian byte order to an integer.
+ */
+unsigned long long PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_bytes_to_ull(
+ const unsigned char *in, size_t inlen);
+
+/**
+ * Computes a root node given a leaf and an auth path.
+ * Expects address to be complete other than the tree_height and tree_index.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_compute_root(
+ unsigned char *root, const unsigned char *leaf,
+ uint32_t leaf_idx, uint32_t idx_offset,
+ const unsigned char *auth_path, uint32_t tree_height,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+/**
+ * For a given leaf index, computes the authentication path and the resulting
+ * root node using Merkle's TreeHash algorithm.
+ * Expects the layer and tree parts of the tree_addr to be set, as well as the
+ * tree type (i.e. PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_HASHTREE or PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ADDR_TYPE_FORSTREE).
+ * Applies the offset idx_offset to indices before building addresses, so that
+ * it is possible to continue counting indices across trees.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_FORS_HEIGHT(
+ unsigned char *root, unsigned char *auth_path,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t leaf_idx, uint32_t idx_offset,
+ void (*gen_leaf)(
+ unsigned char * /* leaf */,
+ const unsigned char * /* sk_seed */,
+ const unsigned char * /* pub_seed */,
+ uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
+ const hash_state * /* hash_state_seeded */),
+ uint32_t tree_addr[8], const hash_state *hash_state_seeded);
+
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
+ unsigned char *root, unsigned char *auth_path,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t leaf_idx, uint32_t idx_offset,
+ void (*gen_leaf)(
+ unsigned char * /* leaf */,
+ const unsigned char * /* sk_seed */,
+ const unsigned char * /* pub_seed */,
+ uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
+ const hash_state * /* hash_state_seeded */),
+ uint32_t tree_addr[8], const hash_state *hash_state_seeded);
+
+#endif
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c
new file mode 100644
index 000000000..40a615ea1
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.c
@@ -0,0 +1,167 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "address.h"
+#include "hash.h"
+#include "hash_state.h"
+#include "params.h"
+#include "thash.h"
+#include "utils.h"
+#include "wots.h"
+
+// TODO clarify address expectations, and make them more uniform.
+// TODO i.e. do we expect types to be set already?
+// TODO and do we expect modifications or copies?
+
+/**
+ * Computes the starting value for a chain, i.e. the secret key.
+ * Expects the address to be complete up to the chain address.
+ */
+static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
+ uint32_t wots_addr[8],
+ const hash_state *hash_state_seeded) {
+ /* Make sure that the hash address is actually zeroed. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0);
+
+ /* Generate sk element. */
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded);
+}
+
+/**
+ * Computes the chaining function.
+ * out and in have to be n-byte arrays.
+ *
+ * Interprets in as start-th value of the chain.
+ * addr has to contain the address of the chain.
+ */
+static void gen_chain(unsigned char *out, const unsigned char *in,
+ unsigned int start, unsigned int steps,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+ uint32_t i;
+
+ /* Initialize out with the value at position 'start'. */
+ memcpy(out, in, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N);
+
+ /* Iterate 'steps' calls to the hash function. */
+ for (i = start; i < (start + steps) && i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_hash_addr(addr, i);
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_thash_1(
+ out, out, pub_seed, addr, hash_state_seeded);
+ }
+}
+
+/**
+ * base_w algorithm as described in draft.
+ * Interprets an array of bytes as integers in base w.
+ * This only works when log_w is a divisor of 8.
+ */
+static void base_w(unsigned int *output, const size_t out_len,
+ const unsigned char *input) {
+ size_t in = 0;
+ size_t out = 0;
+ unsigned char total = 0;
+ unsigned int bits = 0;
+ size_t consumed;
+
+ for (consumed = 0; consumed < out_len; consumed++) {
+ if (bits == 0) {
+ total = input[in];
+ in++;
+ bits += 8;
+ }
+ bits -= PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW;
+ output[out] = (unsigned int)((total >> bits) & (PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1));
+ out++;
+ }
+}
+
+/* Computes the WOTS+ checksum over a message (in base_w). */
+static void wots_checksum(unsigned int *csum_base_w,
+ const unsigned int *msg_base_w) {
+ unsigned int csum = 0;
+ unsigned char csum_bytes[(PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW + 7) / 8];
+ unsigned int i;
+
+ /* Compute checksum. */
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1; i++) {
+ csum += PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1 - msg_base_w[i];
+ }
+
+ /* Convert checksum to base_w. */
+ /* Make sure expected empty zero bits are the least significant bits. */
+ csum = csum << (8 - ((PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2 * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LOGW) % 8));
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_ull_to_bytes(
+ csum_bytes, sizeof(csum_bytes), csum);
+ base_w(csum_base_w, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN2, csum_bytes);
+}
+
+/* Takes a message and derives the matching chain lengths. */
+static void chain_lengths(unsigned int *lengths, const unsigned char *msg) {
+ base_w(lengths, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1, msg);
+ wots_checksum(lengths + PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN1, lengths);
+}
+
+/**
+ * WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key
+ * elements and computes the corresponding public key.
+ * It requires the seed pub_seed (used to generate bitmasks and hash keys)
+ * and the address of this WOTS key pair.
+ *
+ * Writes the computed public key to 'pk'.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_gen_pk(
+ unsigned char *pk, const unsigned char *sk_seed,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+ uint32_t i;
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(addr, i);
+ wots_gen_sk(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded);
+ gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N,
+ 0, PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1, pub_seed, addr, hash_state_seeded);
+ }
+}
+
+/**
+ * Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_sign(
+ unsigned char *sig, const unsigned char *msg,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t addr[8], const hash_state *hash_state_seeded) {
+ unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN];
+ uint32_t i;
+
+ chain_lengths(lengths, msg);
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(addr, i);
+ wots_gen_sk(sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sk_seed, addr, hash_state_seeded);
+ gen_chain(sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, 0, lengths[i], pub_seed, addr, hash_state_seeded);
+ }
+}
+
+/**
+ * Takes a WOTS signature and an n-byte message, computes a WOTS public key.
+ *
+ * Writes the computed public key to 'pk'.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_pk_from_sig(
+ unsigned char *pk,
+ const unsigned char *sig, const unsigned char *msg,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded) {
+ unsigned int lengths[PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN];
+ uint32_t i;
+
+ chain_lengths(lengths, msg);
+
+ for (i = 0; i < PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_LEN; i++) {
+ PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_set_chain_addr(addr, i);
+ gen_chain(pk + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N, sig + i * PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_N,
+ lengths[i], PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_W - 1 - lengths[i], pub_seed, addr,
+ hash_state_seeded);
+ }
+}
diff --git a/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h
new file mode 100644
index 000000000..5627cc935
--- /dev/null
+++ b/lib/liboqs/src/sig/sphincs/pqclean_sphincs-shake256-192f-simple_clean/wots.h
@@ -0,0 +1,41 @@
+#ifndef PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_H
+#define PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_WOTS_H
+
+#include "hash_state.h"
+#include "params.h"
+#include <stdint.h>
+
+/**
+ * WOTS key generation. Takes a 32 byte seed for the private key, expands it to
+ * a full WOTS private key and computes the corresponding public key.
+ * It requires the seed pub_seed (used to generate bitmasks and hash keys)
+ * and the address of this WOTS key pair.
+ *
+ * Writes the computed public key to 'pk'.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_gen_pk(
+ unsigned char *pk, const unsigned char *sk_seed,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+/**
+ * Takes a n-byte message and the 32-byte seed for the private key to compute a
+ * signature that is placed at 'sig'.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_sign(
+ unsigned char *sig, const unsigned char *msg,
+ const unsigned char *sk_seed, const unsigned char *pub_seed,
+ uint32_t addr[8], const hash_state *hash_state_seeded);
+
+/**
+ * Takes a WOTS signature and an n-byte message, computes a WOTS public key.
+ *
+ * Writes the computed public key to 'pk'.
+ */
+void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_wots_pk_from_sig(
+ unsigned char *pk,
+ const unsigned char *sig, const unsigned char *msg,
+ const unsigned char *pub_seed, uint32_t addr[8],
+ const hash_state *hash_state_seeded);
+
+#endif