Skip to content

Plonk verifier KZG multi point verification

Critical severity GitHub Reviewed Published Oct 16, 2023 in Consensys/gnark • Updated Jan 26, 2024

Package

gomod github.com/consensys/gnark (Go)

Affected versions

< 0.9.1

Patched versions

0.9.1

Description

Impact

The vulnerability allows a third party to derive a valid proof from a valid initial tuple {proof, public_inputs}, corresponding to the same public inputs as the initial proof. It is due to a randomness being generated using a small part of the scratch memory describing the state, allowing for degrees of freedom in the transcript.

Note that the impact is limited to the PlonK verifier smart contract.

Patches

We still use a hash function on some data to have a pseudo rng, but instead of hashing the first 32 bytes of the state (
let random := mod(keccak256(state, 0x20), r_mod) )

we hash the whole state at this point of the verifier as if it was a Fiat Shamir transcript:

        mstore(mPtr, mload(add(state, STATE_FOLDED_DIGESTS_X)))
        mstore(add(mPtr, 0x20), mload(add(state, STATE_FOLDED_DIGESTS_Y)))
        mstore(add(mPtr, 0x40), calldataload(add(aproof, PROOF_BATCH_OPENING_AT_ZETA_X)))
        mstore(add(mPtr, 0x60), calldataload(add(aproof, PROOF_BATCH_OPENING_AT_ZETA_Y)))
        mstore(add(mPtr, 0x80), calldataload(add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X)))
        mstore(add(mPtr, 0xa0), calldataload(add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_Y)))
        mstore(add(mPtr, 0xc0), calldataload(add(aproof, PROOF_OPENING_AT_ZETA_OMEGA_X)))
        mstore(add(mPtr, 0xe0), calldataload(add(aproof, PROOF_OPENING_AT_ZETA_OMEGA_Y)))
        mstore(add(mPtr, 0x100), mload(add(state, STATE_ZETA)))
        mstore(add(mPtr, 0x120), mload(add(state, STATE_GAMMA_KZG)))
        let random := staticcall(gas(), 0x2, mPtr, 0x140, mPtr, 0x20)

Workarounds

In the function batch_verify_multi_points, the variable random (corresponding to u in the paper, step 12 of the plonk verification process) should depend on state_folded_digests_x, state_folded_digests_y, proof_grand_product_commitment_x, proof_grand_product_commitment_y and state_zeta (by hashing those values for instance).

References

@gbotrel gbotrel published to Consensys/gnark Oct 16, 2023
Published to the GitHub Advisory Database Oct 17, 2023
Reviewed Oct 17, 2023
Last updated Jan 26, 2024

Severity

Critical

Weaknesses

No CWEs

CVE ID

No known CVE

GHSA ID

GHSA-7p92-x423-vwj6

Source code

Credits

Checking history
See something to contribute? Suggest improvements for this vulnerability.