From 51b2d443acad7c69d414b441c1636060842c865b Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Sat, 3 Jan 2026 08:48:16 +0800 Subject: [PATCH] CT: Declassify sig in test instead of at the end of signing Alternative to https://github.com/pq-code-package/mldsa-native/pull/822 that I hope to be less controversial. Currently the constant time tests for verification rely on the signature being declassified at the end of verification. This is not ideal. This commit moves this declassification to the constant-time test instead. As suggested in https://github.com/pq-code-package/mldsa-native/pull/822#pullrequestreview-3622033348, there is more work left to clean up the story around declassifications. This PR is a first step towards cleaning up that story to unblock https://github.com/pq-code-package/mldsa-native/pull/825 and https://github.com/pq-code-package/mldsa-native/pull/821, but there is more work left. Signed-off-by: Matthias J. Kannwischer --- mldsa/src/sign.c | 8 ++++---- test/test_mldsa.c | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/mldsa/src/sign.c b/mldsa/src/sign.c index 02dd6e192..01d5973b2 100644 --- a/mldsa/src/sign.c +++ b/mldsa/src/sign.c @@ -113,6 +113,10 @@ static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES], } #endif /* MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST */ + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(signature, MLDSA_CRYPTO_BYTES); + /* Verify the signature using the (potentially corrupted) public key */ ret = crypto_sign_verify(signature, siglen, message, sizeof(message), NULL, 0, pk_test); @@ -616,10 +620,6 @@ __contract__( } /* All is well - write signature */ - /* Constant time: At this point it is clear that the signature is valid - it - * can, hence, be considered public. */ - MLD_CT_TESTING_DECLASSIFY(h, sizeof(*h)); - MLD_CT_TESTING_DECLASSIFY(z, sizeof(*z)); mld_pack_sig(sig, challenge_bytes, z, h, n); ret = 0; /* success */ diff --git a/test/test_mldsa.c b/test/test_mldsa.c index 5916e45dd..db978199b 100644 --- a/test/test_mldsa.c +++ b/test/test_mldsa.c @@ -49,6 +49,10 @@ static int test_sign_core(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], CHECK(crypto_sign(sm, &smlen, m, MLEN, ctx, CTXLEN, sk) == 0); + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(sm, MLEN + MLDSA_CRYPTO_BYTES); + rc = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); /* Constant time: Declassify outputs to check them. */ @@ -120,6 +124,11 @@ static int test_sign_extmu(void) MLD_CT_TESTING_SECRET(mu, sizeof(mu)); CHECK(crypto_sign_signature_extmu(sig, &siglen, mu, sk) == 0); + + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(sig, MLDSA_CRYPTO_BYTES); + CHECK(crypto_sign_verify_extmu(sig, siglen, mu, pk) == 0); return 0; @@ -147,6 +156,11 @@ static int test_sign_pre_hash(void) CHECK(crypto_sign_signature_pre_hash_shake256(sig, &siglen, m, MLEN, ctx, CTXLEN, rnd, sk) == 0); + + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(sig, MLDSA_CRYPTO_BYTES); + CHECK(crypto_sign_verify_pre_hash_shake256(sig, siglen, m, MLEN, ctx, CTXLEN, pk) == 0); @@ -240,6 +254,10 @@ static int test_wrong_pk(void) pk[idx] ^= 1; + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(sm, MLEN + MLDSA_CRYPTO_BYTES); + rc = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); /* Constant time: Declassify outputs to check them. */ @@ -291,6 +309,10 @@ static int test_wrong_sig(void) sm[idx] ^= 1; + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(sm, MLEN + MLDSA_CRYPTO_BYTES); + rc = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); /* Constant time: Declassify outputs to check them. */ @@ -343,6 +365,10 @@ static int test_wrong_ctx(void) ctx[idx] ^= 1; + /* Constant time: Declassify signature as it is considered public in + * verification */ + MLD_CT_TESTING_DECLASSIFY(sm, MLEN + MLDSA_CRYPTO_BYTES); + rc = crypto_sign_open(m2, &mlen, sm, smlen, ctx, CTXLEN, pk); /* Constant time: Declassify outputs to check them. */