Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .CMake/alg_support.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ cmake_dependent_option(OQS_ENABLE_KEM_ml_kem_768 "" ON "OQS_ENABLE_KEM_ML_KEM" O
cmake_dependent_option(OQS_ENABLE_KEM_ml_kem_1024 "" ON "OQS_ENABLE_KEM_ML_KEM" OFF)

option(OQS_ENABLE_SIG_ML_DSA "Enable ml_dsa algorithm family" ON)
cmake_dependent_option(OQS_ENABLE_SIG_ML_DSA_RANDOMIZED_SIGNING "Enable randomized signing for ML-DSA" OFF "OQS_ENABLE_SIG_ML_DSA" OFF)
cmake_dependent_option(OQS_ENABLE_SIG_ml_dsa_44 "" ON "OQS_ENABLE_SIG_ML_DSA" OFF)
cmake_dependent_option(OQS_ENABLE_SIG_ml_dsa_65 "" ON "OQS_ENABLE_SIG_ML_DSA" OFF)
cmake_dependent_option(OQS_ENABLE_SIG_ml_dsa_87 "" ON "OQS_ENABLE_SIG_ML_DSA" OFF)
Expand Down
8 changes: 7 additions & 1 deletion CONFIGURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ To enable `XMSS` stateful signature, set `OQS_ENABLE_SIG_STFL_XMSS` to `ON`, the

For a full list of such options and their default values, consult [.CMake/alg_support.cmake](https://github.com/open-quantum-safe/liboqs/blob/master/.CMake/alg_support.cmake).

**Default**: Unset.
### OQS_ENABLE_SIG_ML_DSA_RANDOMIZED_SIGNING

Can be set to `ON` or `OFF`. When `ON`, ML-DSA signature algorithms are built with randomized signing enabled, resulting in non-deterministic signatures (randomized seed/nonce per signature).

This option is only available if `OQS_ENABLE_SIG_ML_DSA` is `ON`.

**Default**: `OFF`.

## OQS_ALGS_ENABLED

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ cmake_dependent_option(OQS_ENABLE_KEM_{{ family['name'] }}_{{ scheme['alias_sche
option(OQS_ENABLE_SIG_{{ family['name']|upper }} "Enable {{ family['name'] }} algorithm family" OFF)
{%- else %}
option(OQS_ENABLE_SIG_{{ family['name']|upper }} "Enable {{ family['name'] }} algorithm family" ON)
{%- endif %}
{%- if family['name'] == "ml_dsa" %}
cmake_dependent_option(OQS_ENABLE_SIG_ML_DSA_RANDOMIZED_SIGNING "Enable randomized signing for ML-DSA" OFF "OQS_ENABLE_SIG_ML_DSA" OFF)
{%- endif %}
{%- for scheme in family['schemes'] %}
cmake_dependent_option(OQS_ENABLE_SIG_{{ family['name'] }}_{{ scheme['scheme'] }} "" ON "OQS_ENABLE_SIG_{{ family['name']|upper }}" OFF)
Expand Down
105 changes: 105 additions & 0 deletions tests/test_sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,101 @@ static OQS_STATUS sig_test_correctness(const char *method_name, bool bitflips_al
return ret;
}

#if defined(OQS_ENABLE_SIG_ML_DSA_RANDOMIZED_SIGNING)
// Test that two signatures of the same message are different.
static OQS_STATUS sig_test_randomized_signing(const char *method_name) {
OQS_SIG *sig = NULL;
uint8_t *public_key = NULL;
uint8_t *secret_key = NULL;
uint8_t *message = NULL;
size_t message_len = 100;
uint8_t *signature1 = NULL;
size_t signature1_len;
uint8_t *signature2 = NULL;
size_t signature2_len;
OQS_STATUS rc, ret = OQS_ERROR;

sig = OQS_SIG_new(method_name);
if (sig == NULL) {
// ML-DSA is not enabled, so we can't test it.
return OQS_SUCCESS;
}

printf("Testing randomized signing for %s\n", sig->method_name);

public_key = OQS_MEM_malloc(sig->length_public_key);
secret_key = OQS_MEM_malloc(sig->length_secret_key);
message = OQS_MEM_malloc(message_len);
signature1 = OQS_MEM_malloc(sig->length_signature);
signature2 = OQS_MEM_malloc(sig->length_signature);

if ((public_key == NULL) || (secret_key == NULL) || (message == NULL) || (signature1 == NULL) || (signature2 == NULL)) {
fprintf(stderr, "ERROR: OQS_MEM_malloc failed\n");
goto err;
}

OQS_randombytes(message, message_len);

rc = OQS_SIG_keypair(sig, public_key, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_keypair failed\n");
goto err;
}

rc = OQS_SIG_sign(sig, signature1, &signature1_len, message, message_len, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_sign failed\n");
goto err;
}

rc = OQS_SIG_sign(sig, signature2, &signature2_len, message, message_len, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_sign failed\n");
goto err;
}

if (signature1_len != signature2_len) {
printf("Signatures have different lengths, so they are not identical.\n");
} else if (memcmp(signature1, signature2, signature1_len) == 0) {
fprintf(stderr, "ERROR: Two signatures of the same message are identical.\n");
goto err;
} else {
printf("Two signatures of the same message are not identical, as expected.\n");
}

rc = OQS_SIG_verify(sig, message, message_len, signature1, signature1_len, public_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_verify failed for signature 1\n");
goto err;
}

rc = OQS_SIG_verify(sig, message, message_len, signature2, signature2_len, public_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_verify failed for signature 2\n");
goto err;
}

printf("verification passes as expected\n");
ret = OQS_SUCCESS;
goto cleanup;

err:
ret = OQS_ERROR;

cleanup:
if (secret_key) {
OQS_MEM_secure_free(secret_key, sig->length_secret_key);
}
OQS_MEM_insecure_free(public_key);
OQS_MEM_insecure_free(message);
OQS_MEM_insecure_free(signature1);
OQS_MEM_insecure_free(signature2);
OQS_SIG_free(sig);

return ret;
}
#endif

#ifdef OQS_ENABLE_TEST_CONSTANT_TIME
static void TEST_SIG_randombytes(uint8_t *random_array, size_t bytes_to_read) {
// We can't make direct calls to the system randombytes on some platforms,
Expand Down Expand Up @@ -349,6 +444,16 @@ int main(int argc, char **argv) {
}
#endif

#if defined(OQS_ENABLE_SIG_ML_DSA_RANDOMIZED_SIGNING)
if (strncmp(alg_name, "ML-DSA", 6) == 0) {
rc = sig_test_randomized_signing(alg_name);
if (rc != OQS_SUCCESS) {
OQS_destroy();
return EXIT_FAILURE;
}
}
#endif

#if OQS_USE_PTHREADS && !defined(OQS_ENABLE_TEST_CONSTANT_TIME)
#define MAX_LEN_SIG_NAME_ 64
// don't run algorithms with large stack usage in threads
Expand Down
Loading