Add bitflip test for trivial SUF-CMA forgeries (#2090)

* add bitflip test to test_sig.c
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* format code
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* - add sig->suf_cma
- add command-line argument to test_sig.c (the number of bitflips)
- update CROSS upstream to SUF-CMA
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* %d to %ld for size_t bitflips

Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* cast argument bitflips to size_t
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* replace atoi() with strtol()
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* cast bit_index to %llu

Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* update bitflip tests:
- revert CROSS to EUF-CMA
- add test_bitflip_message
- exclude stateful signatures for now
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* remove bitflips_as_str in printf
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* test_bitflip as a single function, add support for stateful signatures
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* add OQS_TEST_CT_DECLASSIFY after test_bitflip_stfl
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* [extended tests]
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* more OQS_TEST_CT_DECLASSIFY [extended tests]
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* patch dilithium to add suf-cma
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* run copy_from_upstream.py
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* SUF-CMA in dilithium docs, run copy_from_upstream.py
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* correct sizeof in OQS_randombytes call (thank you @SWilson4!)
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* factor bitflip testing functions out into test_helpers.c
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* --allow-multiple-definition for Windows .dll in test_kem_mem
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

* --allow-multiple-definition for Windows .dll in test_sig and test_sig_stfl
Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>

---------

Signed-off-by: rtjk <47841774+rtjk@users.noreply.github.com>
This commit is contained in:
Marco Gianvecchio 2025-03-14 16:53:05 +01:00 committed by GitHub
parent 8ed50816c1
commit 8ee6039c74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
75 changed files with 434 additions and 99 deletions

View File

@ -19,9 +19,9 @@
| Parameter set | Parameter set alias | Security model | Claimed NIST Level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) |
|:---------------:|:----------------------|:-----------------|---------------------:|--------------------------:|--------------------------:|-------------------------:|
| Dilithium2 | NA | EUF-CMA | 2 | 1312 | 2528 | 2420 |
| Dilithium3 | NA | EUF-CMA | 3 | 1952 | 4000 | 3293 |
| Dilithium5 | NA | EUF-CMA | 5 | 2592 | 4864 | 4595 |
| Dilithium2 | NA | SUF-CMA | 2 | 1312 | 2528 | 2420 |
| Dilithium3 | NA | SUF-CMA | 3 | 1952 | 4000 | 3293 |
| Dilithium5 | NA | SUF-CMA | 5 | 2592 | 4864 | 4595 |
## Dilithium2 implementation characteristics

View File

@ -28,7 +28,7 @@ parameter-sets:
- name: Dilithium2
oqs_alg: OQS_SIG_alg_dilithium_2
claimed-nist-level: 2
claimed-security: EUF-CMA
claimed-security: SUF-CMA
length-public-key: 1312
length-secret-key: 2528
length-signature: 2420
@ -72,7 +72,7 @@ parameter-sets:
- name: Dilithium3
oqs_alg: OQS_SIG_alg_dilithium_3
claimed-nist-level: 3
claimed-security: EUF-CMA
claimed-security: SUF-CMA
length-public-key: 1952
length-secret-key: 4000
length-signature: 3293
@ -116,7 +116,7 @@ parameter-sets:
- name: Dilithium5
oqs_alg: OQS_SIG_alg_dilithium_5
claimed-nist-level: 5
claimed-security: EUF-CMA
claimed-security: SUF-CMA
length-public-key: 2592
length-secret-key: 4864
length-signature: 4595

View File

@ -368,7 +368,12 @@ def load_instructions(file='copy_from_upstream.yml'):
raise RuntimeError("Found duplicate arch {} in scheme {}".format(arch, scheme))
scheme['scheme_paths'][arch] = (os.path.join('repos', location,
upstreams[location]['sig_scheme_path'].format_map(scheme)))
# assume EUF-CMA for schemes that don't specify a security classification
scheme['metadata']['euf_cma'] = 'true'
scheme['metadata']['suf_cma'] = 'false'
if 'claimed-security' in metadata:
if metadata['claimed-security'] == "SUF-CMA":
scheme['metadata']['suf_cma'] = 'true'
scheme['pqclean_scheme_c'] = scheme['pqclean_scheme'].replace('-', '')
scheme['scheme_c'] = scheme['scheme'].replace('-', '')
scheme['default_implementation'] = family['default_implementation']

View File

@ -53,7 +53,7 @@ upstreams:
git_commit: 3e9b9f1412f6c7435dbeb4e10692ea58f181ee51
sig_meta_path: '{pretty_name_full}_META.yml'
sig_scheme_path: '.'
patches: [pqcrystals-dilithium-yml.patch, pqcrystals-dilithium-ref-shake-aes.patch, pqcrystals-dilithium-avx2-shake-aes.patch]
patches: [pqcrystals-dilithium-yml.patch, pqcrystals-dilithium-ref-shake-aes.patch, pqcrystals-dilithium-avx2-shake-aes.patch, pqcrystals-dilithium-SUF-CMA.patch]
-
name: pqcrystals-dilithium-standard
git_url: https://github.com/pq-crystals/dilithium.git
@ -61,7 +61,7 @@ upstreams:
git_commit: 444cdcc84eb36b66fe27b3a2529ee48f6d8150c2
sig_meta_path: '{pretty_name_full}_META.yml'
sig_scheme_path: '.'
patches: [pqcrystals-ml_dsa.patch]
patches: [pqcrystals-ml_dsa.patch, pqcrystals-ml_dsa-SUF-CMA.patch]
-
name: pqmayo
git_url: https://github.com/PQCMayo/MAYO-C.git

View File

@ -0,0 +1,73 @@
ef30acde710cc1fcb0ed9735af3631761ed0358a
diff --git a/Dilithium2-AES_META.yml b/Dilithium2-AES_META.yml
index bad46d3..ce6e854 100644
--- a/Dilithium2-AES_META.yml
+++ b/Dilithium2-AES_META.yml
@@ -1,6 +1,7 @@
name: Dilithium2-AES
type: signature
claimed-nist-level: 2
+claimed-security: SUF-CMA
length-public-key: 1312
length-secret-key: 2528
length-signature: 2420
diff --git a/Dilithium2_META.yml b/Dilithium2_META.yml
index f4b7e8f..1b23d3e 100644
--- a/Dilithium2_META.yml
+++ b/Dilithium2_META.yml
@@ -1,6 +1,7 @@
name: Dilithium2
type: signature
claimed-nist-level: 2
+claimed-security: SUF-CMA
length-public-key: 1312
length-secret-key: 2528
length-signature: 2420
diff --git a/Dilithium3-AES_META.yml b/Dilithium3-AES_META.yml
index 0269442..5153309 100644
--- a/Dilithium3-AES_META.yml
+++ b/Dilithium3-AES_META.yml
@@ -1,6 +1,7 @@
name: Dilithium3-AES
type: signature
claimed-nist-level: 3
+claimed-security: SUF-CMA
length-public-key: 1952
length-secret-key: 4000
length-signature: 3293
diff --git a/Dilithium3_META.yml b/Dilithium3_META.yml
index f45c859..e4fbed2 100644
--- a/Dilithium3_META.yml
+++ b/Dilithium3_META.yml
@@ -1,6 +1,7 @@
name: Dilithium3
type: signature
claimed-nist-level: 3
+claimed-security: SUF-CMA
length-public-key: 1952
length-secret-key: 4000
length-signature: 3293
diff --git a/Dilithium5-AES_META.yml b/Dilithium5-AES_META.yml
index 0128a32..e53bd7d 100644
--- a/Dilithium5-AES_META.yml
+++ b/Dilithium5-AES_META.yml
@@ -1,6 +1,7 @@
name: Dilithium5-AES
type: signature
claimed-nist-level: 5
+claimed-security: SUF-CMA
length-public-key: 2592
length-secret-key: 4864
length-signature: 4595
diff --git a/Dilithium5_META.yml b/Dilithium5_META.yml
index 618b617..8c1aa5f 100644
--- a/Dilithium5_META.yml
+++ b/Dilithium5_META.yml
@@ -1,6 +1,7 @@
name: Dilithium5
type: signature
claimed-nist-level: 5
+claimed-security: SUF-CMA
length-public-key: 2592
length-secret-key: 4864
length-signature: 4595

View File

@ -0,0 +1,37 @@
7bea92142e58c38ec863069a3de2044de4022ac5
diff --git a/ML-DSA-44_META.yml b/ML-DSA-44_META.yml
index 2d5686a..98a8376 100644
--- a/ML-DSA-44_META.yml
+++ b/ML-DSA-44_META.yml
@@ -1,6 +1,7 @@
name: ML-DSA-44
type: signature
claimed-nist-level: 2
+claimed-security: SUF-CMA
length-public-key: 1312
length-secret-key: 2560
length-signature: 2420
diff --git a/ML-DSA-65_META.yml b/ML-DSA-65_META.yml
index 47a4ba0..747a4ff 100644
--- a/ML-DSA-65_META.yml
+++ b/ML-DSA-65_META.yml
@@ -1,6 +1,7 @@
name: ML-DSA-65
type: signature
claimed-nist-level: 3
+claimed-security: SUF-CMA
length-public-key: 1952
length-secret-key: 4032
length-signature: 3309
diff --git a/ML-DSA-87_META.yml b/ML-DSA-87_META.yml
index e9bff1e..632703a 100644
--- a/ML-DSA-87_META.yml
+++ b/ML-DSA-87_META.yml
@@ -1,6 +1,7 @@
name: ML-DSA-87
type: signature
claimed-nist-level: 5
+claimed-security: SUF-CMA
length-public-key: 2592
length-secret-key: 4896
length-signature: 4627

View File

@ -21,6 +21,7 @@ OQS_SIG *OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_new(void) {
sig->claimed_nist_level = {{ scheme['metadata']['claimed-nist-level'] }};
sig->euf_cma = {{ scheme['metadata']['euf_cma'] }};
sig->suf_cma = {{ scheme['metadata']['suf_cma'] }};
{%- if 'api-with-context-string' in default_impl and default_impl['api-with-context-string'] %}
sig->sig_with_ctx_support = true;
{%- else %}
@ -58,6 +59,7 @@ OQS_SIG *OQS_SIG_{{ family }}_{{ scheme['alias_scheme'] }}_new(void) {
sig->claimed_nist_level = {{ scheme['metadata']['claimed-nist-level'] }};
sig->euf_cma = {{ scheme['metadata']['euf_cma'] }};
sig->suf_cma = {{ scheme['metadata']['suf_cma'] }};
sig->length_public_key = OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_public_key;
sig->length_secret_key = OQS_SIG_{{ family }}_{{ scheme['scheme'] }}_length_secret_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_128_balanced_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_128_balanced_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_128_fast_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_128_fast_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_128_small_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_128_small_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_192_balanced_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_192_balanced_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_192_fast_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_192_fast_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_192_small_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_192_small_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_256_balanced_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_256_balanced_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_256_fast_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_256_fast_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdp_256_small_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdp_256_small_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_128_balanced_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_128_balanced_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_128_fast_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_128_fast_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_128_small_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_128_small_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_192_balanced_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_192_balanced_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_192_fast_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_192_fast_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_192_small_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_192_small_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_256_balanced_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_256_balanced_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_256_fast_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_256_fast_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_cross_rsdpg_256_small_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_cross_rsdpg_256_small_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_dilithium_2_new(void) {
sig->claimed_nist_level = 2;
sig->euf_cma = true;
sig->suf_cma = true;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_dilithium_2_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_dilithium_3_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = true;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_dilithium_3_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_dilithium_5_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = true;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_dilithium_5_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_falcon_1024_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_falcon_1024_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_falcon_512_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_falcon_512_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_falcon_padded_1024_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_falcon_padded_1024_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_falcon_padded_512_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_falcon_padded_512_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_mayo_1_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_mayo_1_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_mayo_2_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_mayo_2_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_mayo_3_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_mayo_3_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_mayo_5_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_mayo_5_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_ml_dsa_44_new(void) {
sig->claimed_nist_level = 2;
sig->euf_cma = true;
sig->suf_cma = true;
sig->sig_with_ctx_support = true;
sig->length_public_key = OQS_SIG_ml_dsa_44_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_ml_dsa_65_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = true;
sig->sig_with_ctx_support = true;
sig->length_public_key = OQS_SIG_ml_dsa_65_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_ml_dsa_87_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = true;
sig->sig_with_ctx_support = true;
sig->length_public_key = OQS_SIG_ml_dsa_87_length_public_key;

View File

@ -203,6 +203,9 @@ typedef struct OQS_SIG {
/** Whether the signature offers EUF-CMA security (TRUE) or not (FALSE). */
bool euf_cma;
/** Whether the signature offers SUF-CMA security (TRUE) or not (FALSE). */
bool suf_cma;
/** Whether the signature supports signing with a context string (TRUE) or not (FALSE). */
bool sig_with_ctx_support;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_sha2_128f_simple_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_sha2_128f_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_sha2_128s_simple_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_sha2_128s_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_sha2_192f_simple_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_sha2_192f_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_sha2_192s_simple_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_sha2_192s_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_sha2_256f_simple_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_sha2_256f_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_sha2_256s_simple_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_sha2_256s_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_shake_128f_simple_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_shake_128f_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_shake_128s_simple_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_shake_128s_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_shake_192f_simple_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_shake_192f_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_shake_192s_simple_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_shake_192s_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_shake_256f_simple_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_shake_256f_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_sphincs_shake_256s_simple_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_sphincs_shake_256s_simple_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_III_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_III_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_III_pkc_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_III_pkc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_III_pkc_skc_new(void) {
sig->claimed_nist_level = 3;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_III_pkc_skc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_Ip_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_Ip_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_Ip_pkc_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_Ip_pkc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_Ip_pkc_skc_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_Ip_pkc_skc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_Is_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_Is_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_Is_pkc_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_Is_pkc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_Is_pkc_skc_new(void) {
sig->claimed_nist_level = 1;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_Is_pkc_skc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_V_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_V_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_V_pkc_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_V_pkc_length_public_key;

View File

@ -16,6 +16,7 @@ OQS_SIG *OQS_SIG_uov_ov_V_pkc_skc_new(void) {
sig->claimed_nist_level = 5;
sig->euf_cma = true;
sig->suf_cma = false;
sig->sig_with_ctx_support = false;
sig->length_public_key = OQS_SIG_uov_ov_V_pkc_skc_length_public_key;

View File

@ -80,6 +80,7 @@ OQS_SIG_STFL *OQS_SIG_STFL_alg_lms_##lms_variant##_new(void) { \
sig->method_name = OQS_SIG_STFL_alg_lms_##lms_variant; \
sig->alg_version = "https://datatracker.ietf.org/doc/html/rfc8554"; \
sig->euf_cma = true; \
sig->suf_cma = false; \
\
sig->length_public_key = OQS_SIG_STFL_alg_lms_length_public_key; \
sig->length_secret_key = OQS_SIG_STFL_alg_lms_length_private_key; \

View File

@ -287,6 +287,9 @@ typedef struct OQS_SIG_STFL {
/** Whether the signature offers EUF-CMA security (TRUE) or not (FALSE). */
bool euf_cma;
/** Whether the signature offers SUF-CMA security (TRUE) or not (FALSE). */
bool suf_cma;
/** The (maximum) length, in bytes, of public keys for this signature scheme. */
size_t length_public_key;
/** The (maximum) length, in bytes, of secret keys for this signature scheme. */

View File

@ -40,6 +40,7 @@ OQS_SIG_STFL *OQS_SIG_STFL_alg_xmss##xmss_v##_new(void) { \
sig->method_name = OQS_SIG_STFL_alg_xmss##xmss_v; \
sig->alg_version = "https://datatracker.ietf.org/doc/html/rfc8391"; \
sig->euf_cma = true; \
sig->suf_cma = false; \
\
sig->length_public_key = OQS_SIG_STFL_alg_xmss##xmss_v##_length_pk; \
sig->length_secret_key = OQS_SIG_STFL_alg_xmss##xmss_v##_length_sk; \

View File

@ -79,7 +79,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
endif()
endif()
add_executable(test_kem test_kem.c)
add_executable(test_kem test_kem.c test_helpers.c)
target_link_libraries(test_kem PRIVATE ${TEST_DEPS})
if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
@ -91,8 +91,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
endif()
endif()
add_executable(test_kem_mem test_kem_mem.c)
add_executable(test_kem_mem test_kem_mem.c test_helpers.c)
target_link_libraries(test_kem_mem PRIVATE ${TEST_DEPS})
if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
# workaround for Windows .dll
if(MINGW OR MSYS OR CYGWIN OR CMAKE_CROSSCOMPILING)
target_link_options(test_kem_mem PRIVATE -Wl,--allow-multiple-definition)
else()
target_link_options(test_kem_mem PRIVATE "/FORCE:MULTIPLE")
endif()
endif()
add_executable(speed_kem speed_kem.c)
target_link_libraries(speed_kem PRIVATE ${TEST_DEPS})
@ -138,8 +146,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
endif()
endif()
add_executable(test_sig test_sig.c)
add_executable(test_sig test_sig.c test_helpers.c)
target_link_libraries(test_sig PRIVATE ${TEST_DEPS})
if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
# workaround for Windows .dll
if(CMAKE_CROSSCOMPILING)
target_link_options(test_sig PRIVATE -Wl,--allow-multiple-definition)
else()
target_link_options(test_sig PRIVATE "/FORCE:MULTIPLE")
endif()
endif()
add_executable(test_sig_mem test_sig_mem.c)
target_link_libraries(test_sig_mem PRIVATE ${TEST_DEPS})
@ -151,12 +167,20 @@ target_link_libraries(speed_sig PRIVATE ${TEST_DEPS})
set(SIG_TESTS example_sig kat_sig test_sig test_sig_mem speed_sig vectors_sig)
# SIG_STFL API tests
add_executable(test_sig_stfl test_sig_stfl.c)
add_executable(test_sig_stfl test_sig_stfl.c test_helpers.c)
if((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_C_COMPILER_ID STREQUAL "GNU"))
target_link_libraries(test_sig_stfl PRIVATE ${TEST_DEPS} Threads::Threads)
else ()
target_link_libraries(test_sig_stfl PRIVATE ${TEST_DEPS})
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS)
# workaround for Windows .dll
if(CMAKE_CROSSCOMPILING)
target_link_options(test_sig_stfl PRIVATE -Wl,--allow-multiple-definition)
else()
target_link_options(test_sig_stfl PRIVATE "/FORCE:MULTIPLE")
endif()
endif()
add_executable(speed_sig_stfl speed_sig_stfl.c)
target_link_libraries(speed_sig_stfl PRIVATE ${TEST_DEPS})

View File

@ -48,7 +48,7 @@ int main(void) {
}
printf(" isnull: false\n");
printf(" claimed-nist-level: %d\n", sig->claimed_nist_level);
printf(" claimed-security: %s\n", sig->euf_cma ? "EUF-CMA" : "none");
printf(" claimed-security: %s\n", sig->suf_cma ? "SUF-CMA" : (sig->euf_cma ? "EUF-CMA" : "none"));
printf(" length-public-key: %zu\n", sig->length_public_key);
printf(" length-secret-key: %zu\n", sig->length_secret_key);
printf(" length-signature: %zu\n", sig->length_signature);
@ -66,7 +66,7 @@ int main(void) {
continue;
}
printf(" isnull: false\n");
printf(" claimed-security: %s\n", sig->euf_cma ? "EUF-CMA" : "none");
printf(" claimed-security: %s\n", sig->suf_cma ? "SUF-CMA" : (sig->euf_cma ? "EUF-CMA" : "none"));
printf(" length-public-key: %zu\n", sig->length_public_key);
printf(" length-secret-key: %zu\n", sig->length_secret_key);
printf(" length-signature: %zu\n", sig->length_signature);

View File

@ -155,3 +155,99 @@ void OQS_fprintBstr(FILE *fp, const char *S, const uint8_t *A, size_t L) {
}
fprintf(fp, "\n");
}
OQS_STATUS flip_bit(uint8_t *array, uint64_t array_length, uint64_t bit_position) {
uint64_t byte_index = bit_position / 8;
uint8_t bit_index = bit_position % 8;
if (byte_index >= array_length) {
fprintf(stderr, "ERROR: flip_bit index is out of bounds!\n");
return OQS_ERROR;
}
array[byte_index] ^= (1 << bit_index);
return OQS_SUCCESS;
}
/* flip bits of the message (or signature) one at a time, and check that the verification fails */
OQS_STATUS test_sig_bitflip(OQS_SIG *sig, uint8_t *message, size_t message_len, uint8_t *signature, size_t signature_len, uint8_t *public_key, bool bitflips_all[2], size_t bitflips[2], bool use_ctx, uint8_t *ctx, size_t ctx_i) {
OQS_STATUS rc;
/* the first test (EUF-CMA) flips bits of the message
the second test (SUF-CMA) flips bits of the signature */
int num_tests = sig->suf_cma ? 2 : 1;
for (int test = 0; test < num_tests; test++) {
/* select the array to tamper with (message or signature) */
uint8_t *tampered_array = (test == 1) ? signature : message;
size_t tampered_array_len = (test == 1) ? signature_len : message_len;
/* select the number of bitflips */
uint64_t bitflips_selected = bitflips_all[test] ? tampered_array_len * 8 : bitflips[test];
for (uint64_t i = 0; i < bitflips_selected; i ++) {
uint64_t random_bit_index;
OQS_randombytes((uint8_t *)&random_bit_index, sizeof(random_bit_index));
OQS_TEST_CT_DECLASSIFY(&random_bit_index, sizeof(random_bit_index));
random_bit_index = random_bit_index % (tampered_array_len * 8);
uint64_t bit_index = bitflips_all[test] ? i : random_bit_index;
/* flip the bit */
rc = flip_bit(tampered_array, tampered_array_len, bit_index);
if (rc != OQS_SUCCESS) {
return OQS_ERROR;
}
/* check that the verification fails */
if (use_ctx) {
rc = OQS_SIG_verify_with_ctx_str(sig, message, message_len, signature, signature_len, ctx, ctx_i, public_key);
} else {
rc = OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key);
}
OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_verify should have failed after flipping bit %llu of the %s!\n", (unsigned long long)bit_index, (test == 0) ? "message" : "signature");
return OQS_ERROR;
}
/* flip back the bit */
rc = flip_bit(tampered_array, tampered_array_len, bit_index);
if (rc != OQS_SUCCESS) {
return OQS_ERROR;
}
}
}
return OQS_SUCCESS;
}
/* flip bits of the message (or signature) one at a time, and check that the verification fails */
OQS_STATUS test_sig_stfl_bitflip(OQS_SIG_STFL *sig, uint8_t *message, size_t message_len, uint8_t *signature, size_t signature_len, uint8_t *public_key, bool bitflips_all[2], size_t bitflips[2]) {
OQS_STATUS rc;
/* the first test (EUF-CMA) flips bits of the message
the second test (SUF-CMA) flips bits of the signature */
int num_tests = sig->suf_cma ? 2 : 1;
for (int test = 0; test < num_tests; test++) {
/* select the array to tamper with (message or signature) */
uint8_t *tampered_array = (test == 1) ? signature : message;
size_t tampered_array_len = (test == 1) ? signature_len : message_len;
/* select the number of bitflips */
uint64_t bitflips_selected = bitflips_all[test] ? tampered_array_len * 8 : bitflips[test];
for (uint64_t i = 0; i < bitflips_selected; i ++) {
uint64_t random_bit_index;
OQS_randombytes((uint8_t *)&random_bit_index, sizeof(random_bit_index));
OQS_TEST_CT_DECLASSIFY(&random_bit_index, sizeof(random_bit_index));
random_bit_index = random_bit_index % (tampered_array_len * 8);
uint64_t bit_index = bitflips_all[test] ? i : random_bit_index;
/* flip the bit */
rc = flip_bit(tampered_array, tampered_array_len, bit_index);
if (rc != OQS_SUCCESS) {
return OQS_ERROR;
}
/* check that the verification fails */
rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, public_key);
OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_STFL_verify should have failed after flipping bit %llu of the %s!\n", (unsigned long long)bit_index, (test == 0) ? "message" : "signature");
return OQS_ERROR;
}
/* flip back the bit */
rc = flip_bit(tampered_array, tampered_array_len, bit_index);
if (rc != OQS_SUCCESS) {
return OQS_ERROR;
}
}
}
return OQS_SUCCESS;
}

View File

@ -9,6 +9,15 @@
#include <oqs/sha3.h>
#include <oqs/rand_nist.h>
#ifdef OQS_ENABLE_TEST_CONSTANT_TIME
#include <valgrind/memcheck.h>
#define OQS_TEST_CT_CLASSIFY(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len)
#else
#define OQS_TEST_CT_CLASSIFY(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len)
#endif
typedef union {
OQS_SHA3_shake256_inc_ctx hqc_state;
OQS_NIST_DRBG_struct nist_state;
@ -38,4 +47,10 @@ void OQS_print_hex_string(const char *label, const uint8_t *str, size_t len);
void OQS_fprintBstr(FILE *fp, const char *S, const uint8_t *A, size_t L);
OQS_STATUS flip_bit(uint8_t *array, uint64_t array_length, uint64_t bit_position);
OQS_STATUS test_sig_bitflip(OQS_SIG *sig, uint8_t *message, size_t message_len, uint8_t *signature, size_t signature_len, uint8_t *public_key, bool bitflips_all[2], size_t bitflips[2], bool use_ctx, uint8_t *ctx, size_t ctx_i);
OQS_STATUS test_sig_stfl_bitflip(OQS_SIG_STFL *sig, uint8_t *message, size_t message_len, uint8_t *signature, size_t signature_len, uint8_t *public_key, bool bitflips_all[2], size_t bitflips[2]);
#endif

View File

@ -16,29 +16,12 @@
#include <pthread.h>
#endif
#ifdef OQS_ENABLE_TEST_CONSTANT_TIME
#include <valgrind/memcheck.h>
#define OQS_TEST_CT_CLASSIFY(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len)
#else
#define OQS_TEST_CT_CLASSIFY(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len)
#endif
#ifdef OQS_ENABLE_KEM_ML_KEM
#define MLKEM_SECRET_LEN 32
#endif
#include "system_info.c"
/* Displays hexadecimal strings */
static void OQS_print_hex_string(const char *label, const uint8_t *str, size_t len) {
printf("%-20s (%4zu bytes): ", label, len);
for (size_t i = 0; i < (len); i++) {
printf("%02X", str[i]);
}
printf("\n");
}
#include "test_helpers.h"
#ifdef OQS_ENABLE_KEM_ML_KEM
/* mlkem rejection key testcase */

View File

@ -9,15 +9,7 @@
#include "system_info.c"
#include "tmp_store.c"
/* Displays hexadecimal strings */
static void OQS_print_hex_string(const char *label, const uint8_t *str, size_t len) {
printf("%-20s (%4zu bytes): ", label, len);
for (size_t i = 0; i < (len); i++) {
printf("%02X", str[i]);
}
printf("\n");
}
#include "test_helpers.h"
typedef struct magic_s {
uint8_t val[32];

View File

@ -14,22 +14,14 @@
#include <pthread.h>
#endif
#ifdef OQS_ENABLE_TEST_CONSTANT_TIME
#include <valgrind/memcheck.h>
#define OQS_TEST_CT_CLASSIFY(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len)
#else
#define OQS_TEST_CT_CLASSIFY(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len)
#endif
#include "system_info.c"
#include "test_helpers.h"
typedef struct magic_s {
uint8_t val[31];
} magic_t;
static OQS_STATUS sig_test_correctness(const char *method_name) {
static OQS_STATUS sig_test_correctness(const char *method_name, bool bitflips_all[2], size_t bitflips[2]) {
OQS_SIG *sig = NULL;
uint8_t *public_key = NULL;
@ -52,8 +44,23 @@ static OQS_STATUS sig_test_correctness(const char *method_name) {
goto err;
}
char bitflips_as_str[2][50];
for (int i = 0; i < 2; i++) {
if (bitflips_all[i]) {
snprintf(bitflips_as_str[i], sizeof(bitflips_as_str[i]), "all");
} else {
snprintf(bitflips_as_str[i], sizeof(bitflips_as_str[i]), "%ld random", bitflips[i]);
}
}
printf("================================================================================\n");
printf("Sample computation for signature %s\n", sig->method_name);
if (sig->euf_cma) {
printf("Testing EUF-CMA by flipping %s bits of the message\n", bitflips_as_str[0]);
}
if (sig->suf_cma) {
printf("Testing SUF-CMA by flipping %s bits of the signature\n", bitflips_as_str[1]);
}
printf("Version source: %s\n", sig->alg_version);
printf("================================================================================\n");
@ -110,16 +117,13 @@ static OQS_STATUS sig_test_correctness(const char *method_name) {
goto err;
}
/* modify the signature to invalidate it */
OQS_randombytes(signature, signature_len);
OQS_TEST_CT_DECLASSIFY(signature, signature_len);
rc = OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key);
rc = test_sig_bitflip(sig, message, message_len, signature, signature_len, public_key, bitflips_all, bitflips, false, NULL, 0);
OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_verify should have failed!\n");
if (rc != OQS_SUCCESS) {
goto err;
}
/* testing signing with context, if supported */
OQS_randombytes(ctx, 257);
if (sig->sig_with_ctx_support) {
@ -140,15 +144,12 @@ static OQS_STATUS sig_test_correctness(const char *method_name) {
goto err;
}
/* modify the signature to invalidate it */
OQS_randombytes(signature, signature_len);
OQS_TEST_CT_DECLASSIFY(signature, signature_len);
rc = OQS_SIG_verify_with_ctx_str(sig, message, message_len, signature, signature_len, ctx, i, public_key);
rc = test_sig_bitflip(sig, message, message_len, signature, signature_len, public_key, bitflips_all, bitflips, true, ctx, i);
OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_verify_with_ctx_str should have failed!\n");
if (rc != OQS_SUCCESS) {
goto err;
}
}
rc = OQS_SIG_sign_with_ctx_str(sig, signature, &signature_len, message, message_len, ctx, 256, secret_key);
@ -180,13 +181,9 @@ static OQS_STATUS sig_test_correctness(const char *method_name) {
goto err;
}
/* modify the signature to invalidate it */
OQS_randombytes(signature, signature_len);
OQS_TEST_CT_DECLASSIFY(signature, signature_len);
rc = OQS_SIG_verify_with_ctx_str(sig, message, message_len, signature, signature_len, NULL, 0, public_key);
rc = test_sig_bitflip(sig, message, message_len, signature, signature_len, public_key, bitflips_all, bitflips, true, NULL, 0);
OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_verify_with_ctx_str should have failed!\n");
if (rc != OQS_SUCCESS) {
goto err;
}
@ -249,12 +246,14 @@ static void TEST_SIG_randombytes(uint8_t *random_array, size_t bytes_to_read) {
#if OQS_USE_PTHREADS
struct thread_data {
char *alg_name;
bool *bitflips_all;
size_t *bitflips;
OQS_STATUS rc;
};
void *test_wrapper(void *arg) {
struct thread_data *td = arg;
td->rc = sig_test_correctness(td->alg_name);
td->rc = sig_test_correctness(td->alg_name, td->bitflips_all, td->bitflips);
OQS_thread_stop();
return NULL;
}
@ -265,8 +264,8 @@ int main(int argc, char **argv) {
printf("Testing signature algorithms using liboqs version %s\n", OQS_version());
if (argc != 2) {
fprintf(stderr, "Usage: test_sig algname\n");
if (argc < 2 || argc > 4) {
fprintf(stderr, "Usage: test_sig algname [bitflips_msg] [bitflips_sig]\n");
fprintf(stderr, " algname: ");
for (size_t i = 0; i < OQS_SIG_algs_length; i++) {
if (i > 0) {
@ -275,6 +274,8 @@ int main(int argc, char **argv) {
fprintf(stderr, "%s", OQS_SIG_alg_identifier(i));
}
fprintf(stderr, "\n");
fprintf(stderr, " bitflips_msg: the number of random bitflips to perform for each EUF-CMA signature (\"all\" to flip every bit)\n");
fprintf(stderr, " bitflips_sig: the number of random bitflips to perform for each SUF-CMA signature (\"all\" to flip every bit)\n");
OQS_destroy();
return EXIT_FAILURE;
}
@ -288,6 +289,24 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
/* by default, flip 50 random bits of the message and signature (to test EUF-CMA and SUF-CMA, respectively) */
bool bitflips_all[2] = {false, false};
size_t bitflips[2] = {50, 50};
if (argc >= 3) {
if (strcmp(argv[2], "all") == 0) {
bitflips_all[0] = true;
} else {
bitflips[0] = (size_t)strtol(argv[2], NULL, 10);
}
}
if (argc == 4) {
if (strcmp(argv[3], "all") == 0) {
bitflips_all[1] = true;
} else {
bitflips[1] = (size_t)strtol(argv[3], NULL, 10);
}
}
#ifdef OQS_ENABLE_TEST_CONSTANT_TIME
OQS_randombytes_custom_algorithm(&TEST_SIG_randombytes);
#else
@ -308,8 +327,7 @@ int main(int argc, char **argv) {
}
if (test_in_thread) {
pthread_t thread;
struct thread_data td;
td.alg_name = alg_name;
struct thread_data td = {.alg_name = alg_name, .bitflips_all = bitflips_all, .bitflips = bitflips, .rc = OQS_ERROR};
int trc = pthread_create(&thread, NULL, test_wrapper, &td);
if (trc) {
fprintf(stderr, "ERROR: Creating pthread\n");
@ -319,10 +337,10 @@ int main(int argc, char **argv) {
pthread_join(thread, NULL);
rc = td.rc;
} else {
rc = sig_test_correctness(alg_name);
rc = sig_test_correctness(alg_name, bitflips_all, bitflips);
}
#else
rc = sig_test_correctness(alg_name);
rc = sig_test_correctness(alg_name, bitflips_all, bitflips);
#endif
if (rc != OQS_SUCCESS) {
OQS_destroy();

View File

@ -19,6 +19,7 @@
#include <oqs/oqs.h>
#include "tmp_store.c"
#include "system_info.c"
#include "test_helpers.h"
#if OQS_USE_PTHREADS_IN_TESTS
#include <pthread.h>
@ -26,15 +27,6 @@ static pthread_mutex_t *test_sk_lock = NULL;
static pthread_mutex_t *sk_lock = NULL;
#endif
#ifdef OQS_ENABLE_TEST_CONSTANT_TIME
#include <valgrind/memcheck.h>
#define OQS_TEST_CT_CLASSIFY(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len)
#else
#define OQS_TEST_CT_CLASSIFY(addr, len)
#define OQS_TEST_CT_DECLASSIFY(addr, len)
#endif
#ifdef __GNUC__
#define UNUSED __attribute__((unused))
#else
@ -407,7 +399,7 @@ static char *convert_method_name_to_file_name(const char *method_name) {
return strdup(file_store);
}
static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char *katfile) {
static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char *katfile, bool bitflips_all[2], size_t bitflips[2]) {
OQS_SIG_STFL *sig = NULL;
uint8_t *public_key = NULL;
@ -439,8 +431,24 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char
goto err;
}
char bitflips_as_str[2][50];
for (int i = 0; i < 2; i++) {
if (bitflips_all[i]) {
snprintf(bitflips_as_str[i], sizeof(bitflips_as_str[i]), "all");
} else {
snprintf(bitflips_as_str[i], sizeof(bitflips_as_str[i]), "%ld random", bitflips[i]);
}
}
printf("================================================================================\n");
printf("Sample computation for stateful signature %s\n", sig->method_name);
printf("Sample computation for signature %s\n", sig->method_name);
if (sig->euf_cma) {
printf("Testing EUF-CMA by flipping %s bits of the message\n", bitflips_as_str[0]);
}
if (sig->suf_cma) {
printf("Testing SUF-CMA by flipping %s bits of the signature\n", bitflips_as_str[1]);
}
printf("Version source: %s\n", sig->alg_version);
printf("================================================================================\n");
@ -540,13 +548,9 @@ static OQS_STATUS sig_stfl_test_correctness(const char *method_name, const char
fprintf(stderr, "ERROR: 2nd Verify with restored public key OQS_SIG_STFL_verify failed\n");
}
/* modify the signature to invalidate it */
OQS_randombytes(signature, signature_len);
OQS_TEST_CT_DECLASSIFY(signature, signature_len);
rc = OQS_SIG_STFL_verify(sig, message, message_len, signature, signature_len, public_key);
rc = test_sig_stfl_bitflip(sig, message, message_len, signature, signature_len, public_key, bitflips_all, bitflips);
OQS_TEST_CT_DECLASSIFY(&rc, sizeof rc);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_STFL_verify should have failed!\n");
if (rc != OQS_SUCCESS) {
goto err;
}
@ -976,6 +980,8 @@ err:
typedef struct thread_data {
const char *alg_name;
const char *katfile;
bool *bitflips_all;
size_t *bitflips;
OQS_STATUS rc;
// OQS_STATUS rc1;
} thread_data_t;
@ -1015,7 +1021,7 @@ void *test_create_keys(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->rc = sig_stfl_test_correctness(td->alg_name, td->katfile, td->bitflips_all, td->bitflips);
OQS_thread_stop();
return NULL;
}
@ -1062,8 +1068,8 @@ int main(int argc, char **argv) {
printf("Testing stateful signature algorithms using liboqs version %s\n", OQS_version());
if (argc < 2) {
fprintf(stderr, "Usage: test_sig_stfl algname [katfile]\n");
if (argc < 2 || argc > 5) {
fprintf(stderr, "Usage: test_sig_stfl algname [katfile] [bitflips_msg] [bitflips_sig]\n");
fprintf(stderr, " algname: ");
for (size_t i = 0; i < OQS_SIG_STFL_algs_length; i++) {
if (i > 0) {
@ -1072,6 +1078,8 @@ int main(int argc, char **argv) {
fprintf(stderr, "%s", OQS_SIG_STFL_alg_identifier(i));
}
fprintf(stderr, "\n");
fprintf(stderr, " bitflips_msg: the number of random bitflips to perform for each EUF-CMA signature (\"all\" to flip every bit)\n");
fprintf(stderr, " bitflips_sig: the number of random bitflips to perform for each SUF-CMA signature (\"all\" to flip every bit)\n");
OQS_destroy();
return EXIT_FAILURE;
}
@ -1090,8 +1098,26 @@ int main(int argc, char **argv) {
}
}
/* by default, flip 50 random bits of the message and signature (to test EUF-CMA and SUF-CMA, respectively) */
bool bitflips_all[2] = {false, false};
size_t bitflips[2] = {50, 50};
if (argc >= 4) {
if (strcmp(argv[2], "all") == 0) {
bitflips_all[0] = true;
} else {
bitflips[0] = (size_t)strtol(argv[3], NULL, 10);
}
}
if (argc == 5) {
if (strcmp(argv[3], "all") == 0) {
bitflips_all[1] = true;
} else {
bitflips[1] = (size_t)strtol(argv[4], NULL, 10);
}
}
/*
* Tests executed by CI/DI only run algoritms that have been emabled.
* Tests executed by CI/DI only run algoritms that have been enabled.
*
*/
if (!OQS_SIG_STFL_alg_is_enabled(alg_name)) {
@ -1130,8 +1156,8 @@ 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};
thread_data_t td_2 = {.alg_name = alg_name, .katfile = katfile, .rc = OQS_ERROR};
thread_data_t td = {.alg_name = alg_name, .katfile = katfile, .bitflips_all = bitflips_all, .bitflips = bitflips, .rc = OQS_ERROR};
thread_data_t td_2 = {.alg_name = alg_name, .katfile = katfile, .bitflips_all = bitflips_all, .bitflips = bitflips, .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};
@ -1224,7 +1250,7 @@ err:
#endif
return exit_status;
#else
rc = sig_stfl_test_correctness(alg_name, katfile);
rc = sig_stfl_test_correctness(alg_name, katfile, bitflips_all, bitflips);
rc1 = sig_stfl_test_secret_key(alg_name, katfile);
OQS_destroy();