Skip to content

Preserve in-place message on signing failure#1230

Open
fegge wants to merge 1 commit into
mainfrom
ptp/sign-inplace-failure-wipes-message
Open

Preserve in-place message on signing failure#1230
fegge wants to merge 1 commit into
mainfrom
ptp/sign-inplace-failure-wipes-message

Conversation

@fegge

@fegge fegge commented Jun 26, 2026

Copy link
Copy Markdown

Summary

  • Preserve the caller's in-place message buffer when crypto_sign fails before producing a signature.
  • Document the failure behavior for signed-message APIs.
  • Add regression coverage for in-place signing failure and RNG-failure paths.

Validation

  • clang-format -i mldsa/src/sign.c mldsa/src/sign.h mldsa/mldsa_native.h test/src/test_mldsa.c test/src/test_rng_fail.c: passed
  • git diff --check -- mldsa/src/sign.c mldsa/src/sign.h mldsa/mldsa_native.h test/src/test_mldsa.c test/src/test_rng_fail.c: passed
  • make run_func run_rng_fail -j4: passed
  • Not run: ./scripts/format because nixpkgs-fmt is not installed in this local environment
  • Not run: ./scripts/lint because shfmt is not installed in this local environment

Fixes #1217


This work was completed by Trail of Bits as part of the Patch The Planet project in collaboration with OpenAI. The issue was identified primarily by the Codex coding agent, and manually reviewed before submission.

Signed-off-by: Fredrik Dahlgren <fredrik.dahlgren@trailofbits.com>
Comment thread mldsa/src/sign.h
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
*
* On failure, *smlen is set to 0. No partial signed-message output is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter is called sig here. Can we align this across sign.h, api.h, and sign.c, while at it?

I think sig and siglen are more intuitive than sm/smlen. @mkannwischer wdyt

Comment thread mldsa/src/sign.c
Comment on lines +1154 to +1164
uint8_t sig[MLDSA_CRYPTO_BYTES];
size_t siglen;
size_t i;

ret = mld_sign_signature(sig, &siglen, m, mlen, ctx, ctxlen, sk, context);
if (ret != 0)
{
*smlen = 0;
goto cleanup;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not too happy with this additional stack allocation (NB: large allocations should come from MLD_ALLOC/FREE, but that is a simple change).

I agree, though, that's unintuitive that the message is corrupted upon error.

Alternative: If signing fails and sm == m (the only interesting case), copy the message from the tail of sm to m. This isn't pretty, but it does the job, because that tail of sm is guaranteed not to be touched.

Leveling up, though: Why do we need this API in the first place? @mkannwischer can you share some perspectives?

@hanno-becker hanno-becker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the function's behavior is not ideal and should, at the very least, be documented if not changed.

However, I'm hesitant about the additional allocation of MLDSA_CRYPTO_BYTES bytes here.

I see three alternative options; @mkannwischer please chime in:

  1. Just document and warn about the behavior.
  2. For sm == m, restore the message upon failure.
  3. Remove the API altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

In-place signing failure wipes the input message

2 participants