Skip to content

noir_pasport: pubkey offset not bounds-checked against tbs_certificate_len; key can be extracted from the unsigned tail #381

@x-senpai-x

Description

@x-senpai-x

Description

verify_rsa_pubkey_in_tbs accepts an arbitrary prover-supplied pubkey_offset and verifies that the DSC modulus bytes appear at that offset. It does not assert:

pubkey_offset + DSC_KEY_SIZE <= tbs_certificate_len

A prover can point the offset into the unsigned (zero-padded) tail of the 1300-byte buffer, extract attacker-controlled bytes, and have them "verified" against the CSCA signature — even though those bytes were never signed by the CSCA.

Root Cause

verify_rsa_pubkey_in_tbs takes tbs: [u8; N] and pubkey_offset: u32 but has no access to the signed length. The function only checks that modulus bytes match at the offset, with no upper-bound constraint on the offset relative to the authenticated region.

Affected file(s):

File Notes
noir-examples/noir-passport-monolithic/utils/data-check/tbs-pubkey/src/lib.nr verify_rsa_pubkey_in_tbs — missing bound check
noir-examples/noir-passport-monolithic/utils/passport_validity_check/src/lib.nr call site — must thread tbs_certificate_len through

Fix

Add a tbs_certificate_len: u32 parameter to verify_rsa_pubkey_in_tbs and assert the bound before the byte comparison loop:

assert(pubkey_offset + DSC_KEY_SIZE <= tbs_certificate_len);

The call site in passport_validity_check/src/lib.nr must be updated to thread tbs_certificate_len through accordingly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions