Skip to content

test: add point at infinity regression tests for TOB-RIPCTXR-5 - #117

Open
mrtcnk wants to merge 2 commits into
XRPLF:mainfrom
mrtcnk:fix/tob-ripctxr-5-regression-tests
Open

test: add point at infinity regression tests for TOB-RIPCTXR-5#117
mrtcnk wants to merge 2 commits into
XRPLF:mainfrom
mrtcnk:fix/tob-ripctxr-5-regression-tests

Conversation

@mrtcnk

@mrtcnk mrtcnk commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds two regression tests to test_elgamal.c that verify the
library's behavior when homomorphic addition produces the point at
infinity — the core cryptographic condition underlying TOB-RIPCTXR-5.

Tests Added

test_homomorphic_add_point_at_infinity
Verifies that secp256k1_elgamal_add correctly returns 0 (failure) when
the resulting C1 component is the point at infinity. This occurs when two
ciphertexts with equal and opposite randomness r and -r are added
homomorphically: C1_result = r*G + (-r)*G = point at infinity.

test_homomorphic_add_post_mergeinbox_attack
Simulates a post-MergeInbox inbox locking attack (TOB-RIPCTXR-5 variant).
After MergeInbox, CB_IN resets to canonical zero Enc(0; r0_A) with publicly
known randomness r0_A. A malicious sender can craft a Send with
r_send = -r0_A such that the homomorphic addition of CB_IN and the
malicious Send produces C1 = point at infinity. This test verifies that
secp256k1_elgamal_add returns 0, meaning the malicious Send is rejected
at the library level and CB_IN is never updated with an invalid ciphertext.

Test Output

Running test: homomorphic add produces point at infinity...
secp256k1_elgamal_add returned: 0 (expected 0 = failure)
Test passed! Point at infinity correctly rejected.

Running test: post-MergeInbox inbox locking attack (TOB-RIPCTXR-5 variant)...
Malicious Send ciphertext is valid (C1 != infinity): OK
Homomorphic add (CB_IN + malicious Send) returned: 0
Expected: 0 (failure — malicious Send rejected at library level)
Test passed! Malicious Send correctly rejected at library level.
Our fix combined with TOB-RIPCTXR-14 is sufficient.

Security Notes

The post-MergeInbox attack is only fully blocked when combined with
correct return value checking of secp256k1_elgamal_add in the rippled
Send state update — as required by TOB-RIPCTXR-14. Both fixes together
are necessary for complete protection.

Related

  • TOB-RIPCTXR-5: Public ciphertext randomness allows attackers to lock inbox funds
  • TOB-RIPCTXR-14: Missing return value validation

@mrtcnk
mrtcnk requested a review from tesseract-ripple June 3, 2026 04:47
mrtcnk and others added 2 commits July 16, 2026 17:44
- Add test_homomorphic_add_point_at_infinity: verifies secp256k1_elgamal_add
  returns 0 when result C1 is point at infinity
- Add test_homomorphic_add_post_mergeinbox_attack: simulates post-MergeInbox
  inbox locking attack, verifies malicious Send is rejected at library level
- Extract "EncZero" domain tag into CANONICAL_ZERO_DOMAIN macro with a
  comment pointing to generate_canonical_encrypted_zero in src/elgamal.c,
  and derive hash_input length from sizeof() so both stay in sync
- Zero-init result_c1/result_c2 before the failing elgamal_add calls and
  assert they are unmodified on failure (regression for issue XRPLF#115)
- Remove the unconditional "If 1: attack succeeds" printf that printed
  confusingly even when the test passed; move the explanation into the
  block comment above the call
@tesseract-ripple
tesseract-ripple force-pushed the fix/tob-ripctxr-5-regression-tests branch from aa7aceb to 091aa4a Compare July 17, 2026 17:13

@tesseract-ripple tesseract-ripple left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rebased onto current main and addressed review comments. Pushed directly to the PR branch (maintainer edit).

Merge conflict resolution: The conflicts were entirely due to PRs #127/#133 adding the configurable [range_low, range_high] API to secp256k1_elgamal_decrypt — the PR branch was using the old single-arg signature. Resolved by keeping main's test_decryption_boundaries (with the full ranged-API boundary suite) and grafting in the two new test functions.

Additional fixes applied in the follow-up commit:

  1. Domain tag coupling — Extracted "EncZero" into a CANONICAL_ZERO_DOMAIN macro with a comment pointing to generate_canonical_encrypted_zero in src/elgamal.c. All offsets in hash_input are now derived from sizeof(CANONICAL_ZERO_DOMAIN) - 1 rather than the magic literal 7, so a rename in the source will produce a compile-time mismatch rather than a silent wrong-answer test.

  2. Output buffer invariant on failure — Both new tests now zero-initialize result_c1/result_c2 before the failing secp256k1_elgamal_add call and assert the buffers are unmodified after the failure return. This is a regression guard for issue #115 (partial state changes before failure).

  3. Misleading printf removed — The unconditional "If 1: attack succeeds — CB_IN would store point at infinity" line printed even when the test passed. Moved the explanation into the block comment above the call; the test now only prints on success.

Also added <openssl/evp.h> explicitly (required for EVP_Digest in the attack test).

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.

2 participants