From 4871bea19cda1e87e89ddc1184a9772858e52791 Mon Sep 17 00:00:00 2001 From: Norman Ashley Date: Tue, 30 Jan 2024 11:45:30 -0500 Subject: [PATCH] Disable Stateful Signatures in the build by default (#1676) * Disable stateful signature as default. When enabled, key and signature generation is disabled by default. Only signature verification is allowed. Key and signature generation can be enabled by defining OQS_ENABLE_SIG_STFL_KEY_SIG_GEN * Fixed format * Address unused variables * Update .CMake/alg_support.cmake Co-authored-by: Spencer Wilson * Update CONFIGURE.md Co-authored-by: Spencer Wilson * Update example_sig_stfl.c Fixed compile error, unused function. Added a negative test when stateful signature is disabled. * Fix build error. Allow some key generation tests to run as negative tests when key and sig gen is off * Fix format * Fix build error * Fix build error --------- Co-authored-by: Spencer Wilson --- .CMake/alg_support.cmake | 22 ++++- CONFIGURE.md | 18 ++++ src/oqsconfig.h.cmake | 4 + src/sig_stfl/lms/external/hss_keygen.c | 3 + src/sig_stfl/lms/external/hss_sign_inc.c | 3 + src/sig_stfl/lms/sig_stfl_lms_functions.c | 30 +++++++ src/sig_stfl/sig_stfl.c | 17 ++++ src/sig_stfl/xmss/external/xmss.c | 22 +++++ src/sig_stfl/xmss/sig_stfl_xmss_functions.c | 8 +- .../xmss/sig_stfl_xmss_secret_key_functions.c | 4 + src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c | 8 +- tests/example_sig_stfl.c | 33 ++++++- tests/kat_sig_stfl.c | 38 ++++++++ tests/test_sig_stfl.c | 88 +++++++++++++++++-- 14 files changed, 285 insertions(+), 13 deletions(-) diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index d1f9e8daae..bcf6150e7e 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -497,7 +497,7 @@ endif() ##### OQS_COPY_FROM_UPSTREAM_FRAGMENT_ADD_ENABLE_BY_ALG_END -option(OQS_ENABLE_SIG_STFL_XMSS "Enable XMSS algorithm family" ON) +option(OQS_ENABLE_SIG_STFL_XMSS "Enable XMSS algorithm family" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha256_h10 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha256_h16 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmss_sha256_h20 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) @@ -528,7 +528,7 @@ cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_6 "" ON "OQS_ENAB cmake_dependent_option(OQS_ENABLE_SIG_STFL_xmssmt_shake128_h60_12 "" ON "OQS_ENABLE_SIG_STFL_XMSS" OFF) -option(OQS_ENABLE_SIG_STFL_LMS "Enable LMS algorithm family" ON) +option(OQS_ENABLE_SIG_STFL_LMS "Enable LMS algorithm family" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w1 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w2 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h5_w4 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) @@ -563,6 +563,24 @@ cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h10_w8 "" ON "OQS_E cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h15_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_STFL_lms_sha256_h20_w8_h20_w8 "" ON "OQS_ENABLE_SIG_STFL_LMS" OFF) +option(OQS_ENABLE_SIG_STFL_KEY_SIG_GEN "Enable stateful key and signature generation for research and experimentation" OFF) +cmake_dependent_option(OQS_ALLOW_SFTL_KEY_AND_SIG_GEN "" ON "OQS_ENABLE_SIG_STFL_KEY_SIG_GEN" OFF) + +if (${OQS_ENABLE_SIG_STFL_KEY_SIG_GEN} AND ${OQS_ENABLE_SIG_STFL_XMSS}) + set(OQS_ALLOW_XMSS_KEY_AND_SIG_GEN ON) +else() + set(OQS_ALLOW_XMSS_KEY_AND_SIG_GEN OFF) +endif() + +if (${OQS_ENABLE_SIG_STFL_KEY_SIG_GEN} AND ${OQS_ENABLE_SIG_STFL_LMS}) + set(OQS_ALLOW_LMS_KEY_AND_SIG_GEN ON) +else() + set(OQS_ALLOW_LMS_KEY_AND_SIG_GEN OFF) +endif() + +if(OQS_ALLOW_SFTL_KEY_AND_SIG_GEN STREQUAL "ON") + message(STATUS "Experimental stateful key and signature generation is enabled. Ensure secret keys are securely stored to prevent multiple simultaneous sign operations.") +endif() if((OQS_MINIMAL_BUILD STREQUAL "ON")) message(FATAL_ERROR "OQS_MINIMAL_BUILD option ${OQS_MINIMAL_BUILD} no longer supported") diff --git a/CONFIGURE.md b/CONFIGURE.md index d110a6af45..b604ba0bc7 100644 --- a/CONFIGURE.md +++ b/CONFIGURE.md @@ -119,6 +119,24 @@ Dynamically load OpenSSL through `dlopen`. When using liboqs from other cryptogr Only has an effect if the system supports `dlopen` and ELF binary format, such as Linux or BSD family. +## Stateful Hash Based Signatures + +XMSS and LMS are the two supported Hash-Based Signatures schemes. +`OQS_ENABLE_SIG_STFL_XMSS` and `OQS_ENABLE_SIG_STFL_LMS` control these algorithms, which are disabled by default. +A thrid variable, `OQS_ENABLE_SIG_STFL_KEY_SIG_GEN`, also controls the ability to generate keys and signatures. This is also disabled by default. +Each of these variables can be set to `ON` or `OFF`. +When all three are `ON`, stateful signatures are fully functional and can generate key pairs, sign data, and verify signatures. +If `OQS_ENABLE_SIG_STFL_KEY_SIG_GEN` is `OFF` signature verification is the only functional operation. + +Standards bodies, such as NIST, recommend that key and signature generation only by done in hardware in order to best enforce the one-time use of secret keys. +Keys stored in a file system are extremely susceptible to simultaneous use. +When enabled in this library a warning message will be generated by the config process. + +By default, +- `OQS_ENABLE_SIG_STFL_XMSS` is `OFF` +- `OQS_ENABLE_SIG_STFL_LMS` is `OFF` +- `OQS_ENABLE_SIG_STFL_KEY_SIG_GEN` is `OFF`. + **Default**: `OFF`. ## OQS_OPT_TARGET diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake index 9d533a8b27..ac13bf093c 100644 --- a/src/oqsconfig.h.cmake +++ b/src/oqsconfig.h.cmake @@ -237,3 +237,7 @@ #cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h5_w8_h5_w8 1 #cmakedefine OQS_ENABLE_SIG_STFL_lms_sha256_h10_w4_h5_w8 1 +#cmakedefine OQS_ENABLE_SIG_STFL_KEY_SIG_GEN 1 +#cmakedefine OQS_ALLOW_SFTL_KEY_AND_SIG_GEN 1 +#cmakedefine OQS_ALLOW_XMSS_KEY_AND_SIG_GEN 1 +#cmakedefine OQS_ALLOW_LMS_KEY_AND_SIG_GEN 1 \ No newline at end of file diff --git a/src/sig_stfl/lms/external/hss_keygen.c b/src/sig_stfl/lms/external/hss_keygen.c index 71da413325..d85d9626c7 100644 --- a/src/sig_stfl/lms/external/hss_keygen.c +++ b/src/sig_stfl/lms/external/hss_keygen.c @@ -10,6 +10,7 @@ #include "hss_thread.h" #include "lm_common.h" #include "lm_ots_common.h" +#include /* Count the number of 1 bits at the end (lsbits) of the integer */ /* Do it in the obvious way; straightline code may be faster (no */ @@ -51,6 +52,7 @@ static int trailing_1_bits(merkle_index_t n) { * * This returns true on success, false on failure */ +#ifdef OQS_ALLOW_LMS_KEY_AND_SIG_GEN bool hss_generate_private_key( bool (*generate_random)(void *output, size_t length), unsigned levels, @@ -356,6 +358,7 @@ bool hss_generate_private_key( free(temp_buffer); // IGNORE free-check return true; } +#endif /* * The length of the private key diff --git a/src/sig_stfl/lms/external/hss_sign_inc.c b/src/sig_stfl/lms/external/hss_sign_inc.c index 72a8a22c91..ab3112ee03 100644 --- a/src/sig_stfl/lms/external/hss_sign_inc.c +++ b/src/sig_stfl/lms/external/hss_sign_inc.c @@ -16,6 +16,7 @@ #include "hss_internal.h" #include "hss_sign_inc.h" #include "hss_derive.h" +#include /* * Start the process of creating an HSS signature incrementally. Parameters: @@ -28,6 +29,7 @@ * this_is_the_last_signature - if non-NULL, this will be set if this * signature is the last for this private key */ +#ifdef OQS_ALLOW_LMS_KEY_AND_SIG_GEN bool hss_sign_init( struct hss_sign_inc *ctx, struct hss_working_key *w, @@ -217,3 +219,4 @@ bool hss_sign_finalize( hss_zeroize( seed_buff, sizeof seed_buff ); return success; } +#endif diff --git a/src/sig_stfl/lms/sig_stfl_lms_functions.c b/src/sig_stfl/lms/sig_stfl_lms_functions.c index be709fc71c..d0b1559e2d 100644 --- a/src/sig_stfl/lms/sig_stfl_lms_functions.c +++ b/src/sig_stfl/lms/sig_stfl_lms_functions.c @@ -11,6 +11,12 @@ #include "external/hss_internal.h" #include "sig_stfl_lms_wrap.h" +#ifdef __GNUC__ +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + #define DEFAULT_AUX_DATA 10916 /* Use 10+k of aux data (which works well */ /* with the above default parameter set) */ /** @@ -46,6 +52,12 @@ typedef struct OQS_LMS_KEY_DATA { void *context; } oqs_lms_key_data; +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(UNUSED uint8_t *signature, UNUSED size_t *signature_length, UNUSED const uint8_t *message, + UNUSED size_t message_len, UNUSED OQS_SIG_STFL_SECRET_KEY *secret_key) { + return OQS_ERROR; +} +#else OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signature_length, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) { OQS_STATUS status = OQS_ERROR; @@ -117,6 +129,7 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_sign(uint8_t *signature, size_t *signatu } return status; } +#endif OQS_API OQS_STATUS OQS_SIG_STFL_alg_lms_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { @@ -219,6 +232,11 @@ bool LMS_randombytes(void *buffer, size_t length) { return true; } +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +int oqs_sig_stfl_lms_keypair(UNUSED uint8_t *pk, UNUSED OQS_SIG_STFL_SECRET_KEY *sk, UNUSED const uint32_t oid) { + return -1; +} +#else int oqs_sig_stfl_lms_keypair(uint8_t *pk, OQS_SIG_STFL_SECRET_KEY *sk, const uint32_t oid) { int ret = -1; @@ -522,7 +540,14 @@ int oqs_sig_stfl_lms_keypair(uint8_t *pk, OQS_SIG_STFL_SECRET_KEY *sk, const uin ret = 0; return ret; } +#endif +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN +int oqs_sig_stfl_lms_sign(UNUSED OQS_SIG_STFL_SECRET_KEY *sk, UNUSED uint8_t *sm, UNUSED size_t *smlen, + UNUSED const uint8_t *m, UNUSED size_t mlen) { + return -1; +} +#else int oqs_sig_stfl_lms_sign(OQS_SIG_STFL_SECRET_KEY *sk, uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen) { @@ -598,6 +623,7 @@ int oqs_sig_stfl_lms_sign(OQS_SIG_STFL_SECRET_KEY *sk, return 0; } +#endif int oqs_sig_stfl_lms_verify(const uint8_t *m, size_t mlen, const uint8_t *sm, size_t smlen, @@ -714,6 +740,10 @@ OQS_STATUS oqs_deserialize_lms_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_ return OQS_ERROR; } +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN + return OQS_ERROR; +#endif + aux_buf_len = sk_len - lms_sk_len; if (sk->secret_key_data) { // Key data already present diff --git a/src/sig_stfl/sig_stfl.c b/src/sig_stfl/sig_stfl.c index e3a9d0f71c..0f6ebff7af 100644 --- a/src/sig_stfl/sig_stfl.c +++ b/src/sig_stfl/sig_stfl.c @@ -878,21 +878,38 @@ OQS_API OQS_SIG_STFL *OQS_SIG_STFL_new(const char *method_name) { } OQS_API OQS_STATUS OQS_SIG_STFL_keypair(const OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_STFL_SECRET_KEY *secret_key) { +#ifndef OQS_ALLOW_SFTL_KEY_AND_SIG_GEN + (void)sig; + (void)public_key; + (void)secret_key; + return OQS_ERROR; +#else if (sig == NULL || sig->keypair == NULL || sig->keypair(public_key, secret_key) != 0) { return OQS_ERROR; } else { return OQS_SUCCESS; } return OQS_ERROR; +#endif } OQS_API OQS_STATUS OQS_SIG_STFL_sign(const OQS_SIG_STFL *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, OQS_SIG_STFL_SECRET_KEY *secret_key) { +#ifndef OQS_ALLOW_SFTL_KEY_AND_SIG_GEN + (void)sig; + (void)signature; + (void)signature_len; + (void)message; + (void)message_len; + (void)secret_key; + return OQS_ERROR; +#else if (sig == NULL || sig->sign == NULL || sig->sign(signature, signature_len, message, message_len, secret_key) != 0) { return OQS_ERROR; } else { return OQS_SUCCESS; } +#endif } OQS_API OQS_STATUS OQS_SIG_STFL_verify(const OQS_SIG_STFL *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { diff --git a/src/sig_stfl/xmss/external/xmss.c b/src/sig_stfl/xmss/external/xmss.c index 17b40f5627..71d3f0a463 100644 --- a/src/sig_stfl/xmss/external/xmss.c +++ b/src/sig_stfl/xmss/external/xmss.c @@ -6,6 +6,13 @@ #include "utils.h" #include "xmss.h" + +#if defined(__GNUC__) || defined(__clang__) +#define XMSS_UNUSED_ATT __attribute__((unused)) +#else +#define XMSS_UNUSED_ATT +#endif + /* This file provides wrapper functions that take keys that include OIDs to identify the parameter set to be used. After setting the parameters accordingly it falls back to the regular XMSS core functions. */ @@ -25,6 +32,12 @@ it falls back to the regular XMSS core functions. */ * @return an integer value. If the function executes successfully, it will return 0. If there is an * error, it will return -1. */ +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +int xmss_keypair(XMSS_UNUSED_ATT unsigned char *pk, XMSS_UNUSED_ATT unsigned char *sk, XMSS_UNUSED_ATT const uint32_t oid) +{ + return -1; +} +#else int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) { xmss_params params; @@ -42,6 +55,7 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) } return xmss_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN); } +#endif /** * This function parses the XMSS OID from a secret key, uses it to determine the XMSS parameters, and @@ -57,6 +71,13 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid) * @return an integer value. If the function executes successfully, it will return 0. If there is an * error, it will return -1. */ +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +int xmss_sign(XMSS_UNUSED_ATT unsigned char *sk, XMSS_UNUSED_ATT unsigned char *sm, XMSS_UNUSED_ATT unsigned long long *smlen, + XMSS_UNUSED_ATT const unsigned char *m, XMSS_UNUSED_ATT unsigned long long mlen) +{ + return -1; +} +#else int xmss_sign(unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen) @@ -73,6 +94,7 @@ int xmss_sign(unsigned char *sk, } return xmss_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen); } +#endif /** * The function xmss_sign_open verifies a signature and retrieves the original message using the XMSS diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_functions.c b/src/sig_stfl/xmss/sig_stfl_xmss_functions.c index a19cdc7527..ce2df38238 100644 --- a/src/sig_stfl/xmss/sig_stfl_xmss_functions.c +++ b/src/sig_stfl/xmss/sig_stfl_xmss_functions.c @@ -14,7 +14,12 @@ #endif /* -------------- XMSS -------------- */ - +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sign(XMSS_UNUSED_ATT uint8_t *signature, XMSS_UNUSED_ATT size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, + XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { + return OQS_ERROR; +} +#else OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sign(uint8_t *signature, size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { OQS_STATUS status = OQS_SUCCESS; @@ -59,6 +64,7 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_sign(uint8_t *signature, size_t *signat return status; } +#endif OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmss_verify(XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, const uint8_t *signature, size_t signature_len, XMSS_UNUSED_ATT const uint8_t *public_key) { diff --git a/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c b/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c index 40ad786c4e..4f6413a98b 100644 --- a/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c +++ b/src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c @@ -112,6 +112,10 @@ OQS_STATUS OQS_SECRET_KEY_XMSS_inner_serialize_key(uint8_t **sk_buf_ptr, size_t /* Deserialize XMSS byte string into an XMSS secret key data. */ OQS_STATUS OQS_SECRET_KEY_XMSS_deserialize_key(OQS_SIG_STFL_SECRET_KEY *sk, const size_t sk_len, const uint8_t *sk_buf, XMSS_UNUSED_ATT void *context) { +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN + return OQS_ERROR; +#endif + if (sk == NULL || sk_buf == NULL || (sk_len != sk->length_secret_key)) { return OQS_ERROR; } diff --git a/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c b/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c index a3a2257b1c..f5d99705d3 100644 --- a/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c +++ b/src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c @@ -15,7 +15,12 @@ #endif /* -------------- XMSSMT -------------- */ - +#ifndef OQS_ALLOW_SFTL_KEY_AND_SIG_GEN +OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sign(XMSS_UNUSED_ATT uint8_t *signature, XMSS_UNUSED_ATT size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, + XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { + return OQS_ERROR; +} +#else OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sign(uint8_t *signature, size_t *signature_len, XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, XMSS_UNUSED_ATT OQS_SIG_STFL_SECRET_KEY *secret_key) { OQS_STATUS status = OQS_SUCCESS; @@ -60,6 +65,7 @@ OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_sign(uint8_t *signature, size_t *sign return status; } +#endif OQS_API OQS_STATUS OQS_SIG_STFL_alg_xmssmt_verify(XMSS_UNUSED_ATT const uint8_t *message, XMSS_UNUSED_ATT size_t message_len, const uint8_t *signature, size_t signature_len, XMSS_UNUSED_ATT const uint8_t *public_key) { diff --git a/tests/example_sig_stfl.c b/tests/example_sig_stfl.c index cbabee8b14..cdcd9f6472 100644 --- a/tests/example_sig_stfl.c +++ b/tests/example_sig_stfl.c @@ -121,13 +121,44 @@ static OQS_STATUS stfl_example(char *method_name) { } int main(void) { +#ifndef OQS_ALLOW_SFTL_KEY_AND_SIG_GEN OQS_init(); - if (stfl_example((char *)"XMSS-SHA2_10_256") == OQS_SUCCESS && stfl_example((char *)"LMS_SHA256_H10_W4") == OQS_SUCCESS) { + printf("Stateful signature algorithms key and signature generation is not enabled.\n"); + if (stfl_example((char *)"XMSS-SHA2_10_256") == OQS_ERROR && stfl_example((char *)"LMS_SHA256_H10_W4") == OQS_ERROR) { OQS_destroy(); return EXIT_SUCCESS; } else { OQS_destroy(); return EXIT_FAILURE; } +#else + OQS_STATUS lms_status; + OQS_STATUS xmss_status; + OQS_init(); + xmss_status = stfl_example((char *)"XMSS-SHA2_10_256"); + lms_status = stfl_example((char *)"LMS_SHA256_H10_W4"); + OQS_destroy(); + +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN + if (xmss_status == OQS_ERROR) { + xmss_status = OQS_SUCCESS; + } else { + xmss_status = OQS_ERROR; + } +#endif +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN + if (lms_status == OQS_ERROR) { + lms_status = OQS_SUCCESS; + } else { + lms_status = OQS_ERROR; + } +#endif + if ((xmss_status == OQS_SUCCESS) && (lms_status == OQS_SUCCESS)) { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } +#endif } + diff --git a/tests/kat_sig_stfl.c b/tests/kat_sig_stfl.c index 457a5c3778..23ec293e4b 100644 --- a/tests/kat_sig_stfl.c +++ b/tests/kat_sig_stfl.c @@ -243,6 +243,7 @@ OQS_STATUS sig_stfl_kat(const char *method_name, const char *katfile) { OQS_fprintBstr(fh, "msg = ", msg, msg_len); +#ifdef OQS_ALLOW_SFTL_KEY_AND_SIG_GEN rc = OQS_SIG_STFL_sign(sig, signature, &signature_len, msg, msg_len, secret_key); if (rc != OQS_SUCCESS) { fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sign failed!\n", method_name); @@ -289,7 +290,44 @@ OQS_STATUS sig_stfl_kat(const char *method_name, const char *katfile) { ret = OQS_SUCCESS; goto cleanup; +#else + /* + * Signature generation is disabled so only signature verification can be tested. + */ + signature_len = sig->length_signature; + if (!ReadHex(fp_rsp, signature_kat, signature_len, "sm = ")) { + fprintf(stderr, "ERROR: unable to read 'msg' from <%s>\n", katfile); + goto err; + } + + //Echo back the signature read to keep the test tool happy. + fprintf(fh, "smlen = %zu\n", sig->length_signature); + fprintBstr(fh, "sm = ", signature_kat, sig->length_signature); + rc = OQS_SIG_STFL_verify(sig, msg, msg_len, signature_kat, signature_len, public_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_verify failed!\n", method_name); + goto err; + } + + rc = OQS_SIG_STFL_sigs_remaining(sig, &sigs_remain, secret_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sigs_remaining failed!\n", method_name); + goto err; + } + //Update value to keep the test tool happy + fprintf(fh, "remain = %llu\n", sigs_remain - 1); + + rc = OQS_SIG_STFL_sigs_total(sig, &sigs_maximum, secret_key); + if (rc != OQS_SUCCESS) { + fprintf(stderr, "[kat_stfl_sig] %s ERROR: OQS_SIG_STFL_sigs_total failed!\n", method_name); + goto err; + } + fprintf(fh, "max = %llu", sigs_maximum); + + ret = OQS_SUCCESS; + goto cleanup; +#endif err: ret = OQS_ERROR; goto cleanup; diff --git a/tests/test_sig_stfl.c b/tests/test_sig_stfl.c index a8b3e7962d..f0a51aac74 100644 --- a/tests/test_sig_stfl.c +++ b/tests/test_sig_stfl.c @@ -321,11 +321,13 @@ OQS_STATUS sig_stfl_KATs_keygen(OQS_SIG_STFL *sig, uint8_t *public_key, OQS_SIG_ } else { goto from_keygen; } - +#ifdef OQS_ENABLE_SIG_STFL_XMSS from_kats: return sig_stfl_keypair_from_KATs(sig, public_key, secret_key, katfile); +#endif from_keygen: + (void)(katfile); return sig_stfl_keypair_from_keygen(sig, public_key, secret_key); } @@ -947,7 +949,7 @@ typedef struct thread_data { const char *alg_name; const char *katfile; OQS_STATUS rc; - OQS_STATUS rc1; + // OQS_STATUS rc1; } thread_data_t; typedef struct lock_test_data { @@ -980,13 +982,46 @@ void *test_create_keys(void *arg) { return NULL; } -void *test_wrapper(void *arg) { +void *test_correctness_wrapper(void *arg) { struct thread_data *td = arg; td->rc = sig_stfl_test_correctness(td->alg_name, td->katfile); - td->rc1 = sig_stfl_test_secret_key(td->alg_name, td->katfile); return NULL; } + +void *test_secret_key_wrapper(void *arg) { + struct thread_data *td = arg; + td->rc = sig_stfl_test_secret_key(td->alg_name, td->katfile); + return NULL; +} +#endif + +/* + * When key and signature generation is off + * these operations should fail. So flip the results. + */ +static OQS_STATUS update_test_result( OQS_STATUS rc, int xmss_or_lms) { + OQS_STATUS rc_update = rc; + if (xmss_or_lms) { + ; +#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN + if (rc_update == OQS_ERROR) { + rc_update = OQS_SUCCESS; + } else { + rc_update = OQS_ERROR; + } #endif + } else { + ; +#ifndef OQS_ALLOW_LMS_KEY_AND_SIG_GEN + if (rc_update == OQS_ERROR) { + rc_update = OQS_SUCCESS; + } else { + rc_update = OQS_ERROR; + } +#endif + } + return rc_update; +} int main(int argc, char **argv) { OQS_init(); @@ -1012,11 +1047,31 @@ int main(int argc, char **argv) { const char *alg_name = argv[1]; const char *katfile = argv[2]; + int is_xmss = 0; + if (strstr(alg_name, "XMSS") != NULL) { + is_xmss = 1; + } + /* + * Tests executed by CI/DI only run algoritms that have been emabled. + * + */ if (!OQS_SIG_STFL_alg_is_enabled(alg_name)) { printf("Stateful signature algorithm %s not enabled!\n", alg_name); OQS_destroy(); - return EXIT_FAILURE; + if (is_xmss) { +#ifndef OQS_ENABLE_SIG_STFL_XMSS + return EXIT_SUCCESS; +#else + return EXIT_FAILURE; +#endif + } else { +#ifndef OQS_ENABLE_SIG_STFL_LMS + return EXIT_SUCCESS; +#else + return EXIT_FAILURE; +#endif + } } #ifdef OQS_ENABLE_TEST_CONSTANT_TIME @@ -1037,7 +1092,9 @@ int main(int argc, char **argv) { pthread_t sign_key_thread; pthread_t query_key_thread; - thread_data_t td = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR, .rc1 = OQS_ERROR}; + thread_data_t td = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + thread_data_t td_2 = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; + lock_test_data_t td_create = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; lock_test_data_t td_sign = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; lock_test_data_t td_query = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR}; @@ -1057,14 +1114,23 @@ int main(int argc, char **argv) { goto err; } - if (pthread_create(&thread, NULL, test_wrapper, &td)) { + if (pthread_create(&thread, NULL, test_correctness_wrapper, &td)) { fprintf(stderr, "ERROR: Creating pthread for test_wrapper\n"); exit_status = EXIT_FAILURE; goto err; } pthread_join(thread, NULL); rc = td.rc; - rc1 = td.rc1; + rc = update_test_result(rc, is_xmss); + + if (pthread_create(&thread, NULL, test_secret_key_wrapper, &td_2)) { + fprintf(stderr, "ERROR: Creating pthread for test_wrapper_2\n"); + exit_status = EXIT_FAILURE; + goto err; + } + pthread_join(thread, NULL); + rc1 = td_2.rc; + rc1 = update_test_result(rc1, is_xmss); if (pthread_create(&create_key_thread, NULL, test_create_keys, &td_create)) { fprintf(stderr, "ERROR: Creating pthread for test_create_keys\n"); @@ -1073,6 +1139,7 @@ int main(int argc, char **argv) { } pthread_join(create_key_thread, NULL); rc_create = td_create.rc; + rc_create = update_test_result(rc_create, is_xmss); if (pthread_create(&sign_key_thread, NULL, test_sig_gen, &td_sign)) { fprintf(stderr, "ERROR: Creating pthread for test_sig_gen\n"); @@ -1081,6 +1148,7 @@ int main(int argc, char **argv) { } pthread_join(sign_key_thread, NULL); rc_sign = td_sign.rc; + rc_sign = update_test_result(rc_sign, is_xmss); if (pthread_create(&query_key_thread, NULL, test_query_key, &td_query)) { fprintf(stderr, "ERROR: Creating pthread for test_query_key\n"); @@ -1089,6 +1157,7 @@ int main(int argc, char **argv) { } pthread_join(query_key_thread, NULL); rc_query = td_query.rc; + rc_query = update_test_result(rc_query, is_xmss); err: if (test_sk_lock) { @@ -1121,6 +1190,9 @@ int main(int argc, char **argv) { rc1 = sig_stfl_test_secret_key(alg_name, katfile); OQS_destroy(); + rc = update_test_result(rc, is_xmss); + rc1 = update_test_result(rc1, is_xmss); + if (rc != OQS_SUCCESS || rc1 != OQS_SUCCESS) { return EXIT_FAILURE;