Skip to content

EQL ORE block comparator timing depends on where operands first differ #1149

Description

@coderdan

Problem

The ORE block comparator (eql_v3_internal.compare_ore_block_256_term(s), behind every ordered ORE operator and the ORE operator class) takes time that depends on where its operands first differ. A party who can time queries but cannot read the stored ciphertexts, such as an application user, can learn how long a prefix their query value shares with stored values. The constant-time comparator in ore.rs exists to keep exactly that from them.

  • Text (multi-term) values. The array comparator stops at the first unequal term. On PostgreSQL 17.11 (aarch64), a six-term comparison takes about 11 µs when the first term differs and 47 µs when only the sixth does (Welch t below −1500).
  • Single-term values. Each block after the first difference runs extra statements, and the OR short-circuit skips a comparison on each of those blocks. On the machine measured the two effects nearly cancel (t = +4.9 and +13.9). The extra statements alone give t = +388, about 0.7 µs per comparison. Nothing guarantees the cancellation on other hardware or Postgres builds.

PL/pgSQL is not a constant-time environment, so the realistic target is a constant operation count: the same statements and function calls on every path, whatever the operands.

Fix

#1148 rewrites both comparators to a constant operation count (bitmask of differing blocks, branch-free latch, exactly one encrypt() on every path, multi-term values scanned in full) and adds a timing harness at packages/eql/tests/timing/ore_block_256/. After the change: single-term t = +1.8 and +1.1 at about 3–8% cost; six-term t = +4.5 and +2.7 at about 31 µs per comparison, always.

Follow-up

Apply the same pattern to the ORE v2 comparator when it lands in EQL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

SDKbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions