Skip to content

Commit

Permalink
Disable Stateful Signatures in the build by default (#1676)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Update CONFIGURE.md

Co-authored-by: Spencer Wilson <[email protected]>

* 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 <[email protected]>
  • Loading branch information
ashman-p and SWilson4 committed Apr 12, 2024
1 parent b655749 commit 4871bea
Show file tree
Hide file tree
Showing 14 changed files with 285 additions and 13 deletions.
22 changes: 20 additions & 2 deletions .CMake/alg_support.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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")
Expand Down
18 changes: 18 additions & 0 deletions CONFIGURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/oqsconfig.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions src/sig_stfl/lms/external/hss_keygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "hss_thread.h"
#include "lm_common.h"
#include "lm_ots_common.h"
#include <oqs/oqsconfig.h>

/* 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 */
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -356,6 +358,7 @@ bool hss_generate_private_key(
free(temp_buffer); // IGNORE free-check
return true;
}
#endif

/*
* The length of the private key
Expand Down
3 changes: 3 additions & 0 deletions src/sig_stfl/lms/external/hss_sign_inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "hss_internal.h"
#include "hss_sign_inc.h"
#include "hss_derive.h"
#include <oqs/oqsconfig.h>

/*
* Start the process of creating an HSS signature incrementally. Parameters:
Expand All @@ -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,
Expand Down Expand Up @@ -217,3 +219,4 @@ bool hss_sign_finalize(
hss_zeroize( seed_buff, sizeof seed_buff );
return success;
}
#endif
30 changes: 30 additions & 0 deletions src/sig_stfl/lms/sig_stfl_lms_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/sig_stfl/sig_stfl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
22 changes: 22 additions & 0 deletions src/sig_stfl/xmss/external/xmss.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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;
Expand All @@ -42,6 +55,7 @@ int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
}
return xmss_core_keypair(&params, 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
Expand All @@ -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)
Expand All @@ -73,6 +94,7 @@ int xmss_sign(unsigned char *sk,
}
return xmss_core_sign(&params, 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
Expand Down
8 changes: 7 additions & 1 deletion src/sig_stfl/xmss/sig_stfl_xmss_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {

Expand Down
4 changes: 4 additions & 0 deletions src/sig_stfl/xmss/sig_stfl_xmss_secret_key_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 7 additions & 1 deletion src/sig_stfl/xmss/sig_stfl_xmssmt_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {

Expand Down
33 changes: 32 additions & 1 deletion tests/example_sig_stfl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}


Loading

0 comments on commit 4871bea

Please sign in to comment.