Skip to content

fix: ecc/groups audit findings#22864

Merged
suyash67 merged 8 commits into
merge-train/barretenbergfrom
sb/ecc-groups-fixes
May 14, 2026
Merged

fix: ecc/groups audit findings#22864
suyash67 merged 8 commits into
merge-train/barretenbergfrom
sb/ecc-groups-fixes

Conversation

@suyash67
Copy link
Copy Markdown
Contributor

@suyash67 suyash67 commented Apr 29, 2026

Summary

Addresses findings from the ecc/groups audit.

Commits

  • finding 1 — extend batch_affine_double_impl slope formula to include a for curves with a ≠ 0
  • finding 2reject non-canonical x-coordinate encodings in affine_element::from_compressed (Opened its own PR)
  • finding 3 — route ECDSA / Schnorr secret-nonce scalar mul through a new constant-time element::mul_const_time (Montgomery ladder + Coron blinding)
  • finding 4 — handle rhs = ∞ in mixed-coordinate operator+=
  • finding 5 — zero y (and z) in self_set_inf so the infinity representation is canonical
  • finding 6 — fix pairing.FinalExponentiation reference helper to iterate the full 256-bit exponent
  • finding 7 — extend the G1/G2 SRS defenses from fix: harden BN254 G2 SRS ingress #22858 across the bb.js boundary: in SrsInitSrs::execute, SHA-256-verify every fully-present compressed-G1 chunk against BN254_G1_CHUNK_HASHES before decompression, pin g1_points[0] to the canonical generator and g1_points[1] to τ·G after parsing, and SHA-256-pin the 128-byte G2 input. The subgroup check, on-disk G2 hash pin, infinity rejection, and is_in_prime_subgroup implementation itself already landed in fix: harden BN254 G2 SRS ingress #22858.
  • finding 8 — make field::is_zero constant-time

Test plan

  • ecc_tests — pass (audit-related filter: 110 pass, 8 skipped, 0 failures)
  • srs_tests (CrsFactory.*) — pass
  • bbapi_tests — pass (30/30)
  • New regression tests in affine_element.test.cpp, element.test.cpp, pairing.test.cpp, prime_field.test.cpp

@suyash67 suyash67 changed the title audit: ecc / crypto / srs hardening across eight findings fix(bb): ecc / crypto / srs hardening across eight findings Apr 29, 2026
@suyash67 suyash67 force-pushed the sb/ecc-groups-fixes branch from 0a84835 to b61727c Compare April 29, 2026 21:28
@suyash67 suyash67 changed the title fix(bb): ecc / crypto / srs hardening across eight findings fix: ecc/groups audit findings Apr 30, 2026
@suyash67 suyash67 force-pushed the sb/ecc-groups-fixes branch 2 times, most recently from 87d90eb to 327252e Compare May 1, 2026 22:34
Copy link
Copy Markdown
Contributor

@federicobarbacovi federicobarbacovi left a comment

Choose a reason for hiding this comment

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

Looks great, thanks for doing this! Just a few small comments

Comment thread barretenberg/cpp/src/barretenberg/ecc/groups/element_impl.hpp Outdated
}

// Regression test for element +/- affine_element when the affine operand is the infinity sentinel
// on the large-modulus path. The small-modulus path uses a different sentinel (MSB-of-x) and was
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.

It's not clear to me why this bug didn't affect small modulus: the solution doesn't seem to take into account small/large moduli

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The small modulus case already handled the infinity edge case:

} else {
const bool edge_case_trigger = x.is_msb_set() || other.x.is_msb_set();
if (edge_case_trigger) {
if (x.is_msb_set()) {
*this = { other.x, other.y, Fq::one() };
}
return *this;
}
}

But good point regardless, I edited the test to run for all curves.

// verify_bn254_crs_integrity used by get_bn254_g1_data on the C++ download path; without
// it, bb.js (which downloads g1_compressed.dat externally and forwards the bytes here)
// would have no cryptographic gate against a tampered or wrong-trusted-setup payload.
// Partial trailing data is not chunk-hash-verified — instead the post-parse generator and
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.

Can you please explain a bit more why it's ok not to hash check partial final data? Is it ok to have such data?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually this is not a problem in how bb.js initialises SRS because it always fetches either $2^{18}$ or $2^{20}$ points. But still you raise a good point: I added a check if numPoints buffer is NOT a multiple of 4 MiB (so basically a multiple of $2^{17}$, which is true for our use-cases) it'll throw

@suyash67 suyash67 force-pushed the sb/ecc-groups-fixes branch from 327252e to f8a5dbb Compare May 14, 2026 11:26
@suyash67 suyash67 merged commit 26f56c8 into merge-train/barretenberg May 14, 2026
14 checks passed
@suyash67 suyash67 deleted the sb/ecc-groups-fixes branch May 14, 2026 11:44
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