ppad measure
constant-time analysis

Constant-Time Analysis: ppad-poly1305

target
ppad-poly1305 0.4.6
runtime
haskell (GHC 9.10.3 · LLVM 19.1.7), generic (clang 21.1.2)
architectures
aarch64, x86_64, riscv64
meters
wall, instructions, cycles
updated
2026-08-09
auditor
Jared Tobin (jared@ppad.tech)

ppad-poly1305 v0.4.6 is a Haskell implementation of the Poly1305 one-time message authentication code specified by RFC 8439. It avails of NEON hardware acceleration on supporting ARM hosts, making use of C code via GHC's FFI. Fixed-width 256-bit word support is provided by ppad-fixed.

No exploitable secret-dependent timing was found on the analysed surface, viz.

  • the 'mac' one-time MAC function,
  • the 'poly1305_mac_arm' function that dispatches only on NEON-capable ARM hosts, and
  • MAC equality comparison, as implemented by the MAC type's Eq instance.

No exploitable secret-dependent timing was identified in the statically resolved reach of the aarch64, x86_64, and riscv64 builds. The aarch64 and x86_64 assembly corresponding to the Haskell source was produced by GHC's LLVM backend at LLVM 19.1.7; for riscv64 it was procured by lowering the x86_64 LLVM IR. The aarch64 assembly corresponding to the C source (which is only dispatched on aarch64) was procured by clang 21.1.2. See the security analysis for ppad-fixed for details on the timing properties of that dependency.

Dynamically, no constant-time hypothesis for the analysed surface was rejected on any available meter or host. The constant-time test re: MAC equality comparison under the 'instructions' meter on x86_64 is reported as "qualified" only due to the moderate degree of clipping observed while sampling on the host, which doesn't change the verdict.

summary

function aarch64 x86_64 riscv64
mac
Poly1305 one-time MAC (RFC 8439)
SC SC SC·
poly1305_mac_arm
ARM NEON kernel backing mac on NEON-capable ARM hosts
SC S·C· S·C·
(==) (MAC)
constant-time tag comparison
SC SC SC·

no leak detected   leak   qualified   ? inconclusive   · not run    S = substratum   C = censor

method
adversary model

This analysis assumes an adversary capable of:

  • invoking the analysed functions with chosen inputs an arbitrary number of times,
  • measuring execution time with nanosecond precision,
  • measuring retired instruction counts or cycles, where a PMU exists,
  • observing cache state, and
  • observing memory allocation counts and sizes.

A trusted execution environment at the physical layer is assumed; considered out-of-scope are adversaries who can perform attacks over power or electromagnetic emanation-related side channels, speculative execution attacks, and so on.

security property

The security property under consideration is whether the analysed functions "run in constant time," i.e. whether the observable execution of any analysed function, when called with differing sensitive inputs, is indistinguishable to an attacker with the granted capabilities.

Consider the execution trace t(f, x) procured by evaluating an analysed function f on inputs x, where the trace consists of the sequence of instructions executed, the time they take to execute, the memory addresses accessed, and the size and count of allocations made. Then for any sensitive inputs s0 and s1, and any public input p, the property is, up to renaming of base pointers and stack addresses, and modulo any public comparison result, that:

t(f, (s0, p)) == t(f, (s1, p))

where equality is in terms of distribution.

This security property is scrutinized by way of two analyses.

static analysis

substratum v0.3.7 statically scans compiled assembly for variable-time instructions, e.g. conditional and indirect branches, register-indexed memory accesses, division, and variable shifts. It deterministically ascribes facts to instructions, e.g. that they represent control flow, memory addressing, etc., as well as establishes structural roles for them, such as that an instruction functions as an early-return guard or loop-latch. It also traces each fact's timing-relevant operands back to where the values entered the function.

From each audited entry, substratum filters out known runtime patterns and resolves the transitive closure of direct calls and return-frame continuations, scanning the body of every symbol it expands. The walk stops where control goes dynamic, where it leaves the parsed unit, or where the audit prunes it at a callee audited in its own lane. Every stopping edge, pruned callees included, is enumerated under analysis bounds, so the reach is an explicit lower bound rather than an implied whole. Filtered runtime facts are counted as "suppressed" under analysis bounds.

elenchus v0.1.0 is an agentic distillation protocol used to classify and annotate substratum facts. Two agents independently carry out an appraise action, constructing two separate candidate classification sets. One of those agents then carries out a supplemental dissent action that identifies where, if anywhere, the agents disagreed. A third agent then carries out a falsify action that tries to disprove every classification made. Finally, a coordinating agent distills the results, performing its own independent analysis on anything left unresolved, and the auditor accepts or revises every resulting classification. The classification scheme is as follows:

  • benign means the site's timing depends only on public data (lengths, allocation guards, constructor tags, loop counters over public bounds, etc.).
  • input validation marks a branch that rejects malformed input on a public property before any sensitive input-dependent work begins, revealing only the rejection.
  • negligible probability marks a path whose triggering event occurs with cryptographically negligible probability, typically that proportional to the inverse key size.
  • leak is a site whose timing depends on sensitive content. It flags sensitive information an observer could infer (e.g. a scalar byte, a bitlength, Hamming weight).
dynamic analysis

censor v0.4.4 dynamically falsifies constant-time execution. A case fixes a hypothesis (in which one class pins the sensitive input, the other draws it fresh per pair, with public context shared) and streams paired timing differences through a hedged e-process: a mixture of anytime-valid tests for mean shifts, shape asymmetries, and rare-outlier leaks. The displayed p is the anytime-valid p-value associated with the e-process at the stopping time; a hypothesis is rejected when p < α.

A censor run is performed for every hypothesis using every available meter. Wall time is the portable, always-available meter; the 'instructions retired' and 'cycles' meters require a PMU that may be unavailable on some platforms. Raw differences are clipped via a per-meter scale set during warmup, so heavy-tailed measurement noise can neither bankrupt nor inflate the test. The effect interval under each panel is the anytime-valid confidence interval for that (clipped) mean; its endpoints resolve on a grid of roughly 0.1·c. The jitter is the ratio of a measured baseline interquartile range to its median.

results

measure v0.3.1 synthesizes and presents the analyses. substratum and censor results, elenchus annotations, provenance information, and the auditor's written summary are deterministically aggregated, verified, and rendered into this report, which is then signed with the auditor's GPG signature.

findings by function

mac

Crypto.MAC.Poly1305.macsensitive: key (256-bit one-time key)
substratumllvm
isa result symbols walked instructions flagged
aarch64 32 95
x86_64 27 52
riscv64 28 92
class assessment note aarch64 x86_64 riscv64
cond-branch
control-flow
input validation
public 32-byte key-length rejection (Nothing returned before any key material is read)
×1
early-return-guard
← clobbered by call (approximate)
×1
← entry (R4) + immediate (approximate)
cond-branch
control-flow
benign
constructor-tag dispatch on the static poly1305_arm_available capability CAF (per-process CPU property, independent of key and message)
×1
← entry (R1)
×1
← counter
×1
← entry (R1) + immediate
cond-branch
control-flow
benign
chunk control on the public message length: splitAt-16 block dispatch, zero-length terminal test and loop latch, _roll16 byte-presence guards, and set_hi arm selection on the final-chunk length
×74
← load
×39
×74
var-shift
operand-timing
benign
set_hi/shl_limb bit-placement shifts whose count is 8·l or 64-8·l of the public final-chunk length (the only variable-count shifts in the library; key and message bytes never reach a shift count)
portably variable; discharged only on a target documenting arm-dit (aarch64) · intel-doitm (x86_64)
×16
×12
← load
×16
cond-branch
control-flow
benign
GHC closure pointer-tag re-entry tests (tst #0x7) on loop-state closures, deciding evaluation status rather than data
×3
complete fact list — aarch64 ×95 · x86_64 ×52 · riscv64 ×92
aarch64
b.ne LBB68_5
cond-branch
control-flow
$wmac:5411 input validation
b.eq LBB87_2
cond-branch
control-flow
blk_s4TI:8910 benign
b.ne LBB69_3
cond-branch
control-flow
c7BM:5463 benign
b.ge LBB75_21
cond-branch
control-flow
c7Dw:5919 benign
cbz x8, LBB75_22
cond-branch
control-flow
c7Dw:5930 benign
b.le LBB75_23
cond-branch
control-flow
c7Dw:5934 benign
b.gt LBB75_24
cond-branch
control-flow
c7Dw:5943 benign
b.gt LBB75_25
cond-branch
control-flow
c7Dw:5948 benign
b.gt LBB75_26
cond-branch
control-flow
c7Dw:5953 benign
b.gt LBB75_27
cond-branch
control-flow
c7Dw:5958 benign
b.gt LBB75_28
cond-branch
control-flow
c7Dw:5963 benign
b.gt LBB75_29
cond-branch
control-flow
c7Dw:5968 benign
b.gt LBB75_30
cond-branch
control-flow
c7Dw:5973 benign
b.gt LBB75_31
cond-branch
control-flow
c7Dw:5978 benign
b.gt LBB75_32
cond-branch
control-flow
c7Dw:5983 benign
b.gt LBB75_33
cond-branch
control-flow
c7Dw:5988 benign
b.gt LBB75_34
cond-branch
control-flow
c7Dw:5993 benign
b.gt LBB75_35
cond-branch
control-flow
c7Dw:5998 benign
b.gt LBB75_36
cond-branch
control-flow
c7Dw:6003 benign
b.gt LBB75_37
cond-branch
control-flow
c7Dw:6008 benign
b.gt LBB75_38
cond-branch
control-flow
c7Dw:6013 benign
b.lt LBB75_39
cond-branch
control-flow
c7Dw:6018 benign
b.ge LBB75_41
cond-branch
control-flow
c7Dw:6078 benign
lsl x8, x9, x8
var-shift
operand-timing
c7Dw:6083 benign
cbnz x8, LBB75_2
cond-branch
control-flow
c7Dw:6099 benign
b.le LBB75_4
cond-branch
control-flow
c7Dw:6117 benign
b.le LBB75_5
cond-branch
control-flow
c7Dw:6125 benign
b.le LBB75_6
cond-branch
control-flow
c7Dw:6133 benign
b.le LBB75_7
cond-branch
control-flow
c7Dw:6141 benign
b.le LBB75_8
cond-branch
control-flow
c7Dw:6149 benign
b.le LBB75_9
cond-branch
control-flow
c7Dw:6157 benign
b.le LBB75_10
cond-branch
control-flow
c7Dw:6165 benign
b.le LBB75_11
cond-branch
control-flow
c7Dw:6173 benign
b.le LBB75_12
cond-branch
control-flow
c7Dw:6181 benign
b.le LBB75_13
cond-branch
control-flow
c7Dw:6189 benign
b.le LBB75_14
cond-branch
control-flow
c7Dw:6197 benign
b.le LBB75_15
cond-branch
control-flow
c7Dw:6205 benign
b.le LBB75_16
cond-branch
control-flow
c7Dw:6213 benign
b.le LBB75_17
cond-branch
control-flow
c7Dw:6221 benign
b.le LBB75_18
cond-branch
control-flow
c7Dw:6229 benign
b.ge LBB75_19
cond-branch
control-flow
c7Dw:6237 benign
b.eq LBB75_43
cond-branch
control-flow
c7Dw:6314 benign
b.ge LBB80_23
cond-branch
control-flow
c7KV:7122 benign
cbz x8, LBB80_24
cond-branch
control-flow
c7KV:7137 benign
b.le LBB80_25
cond-branch
control-flow
c7KV:7141 benign
b.gt LBB80_26
cond-branch
control-flow
c7KV:7150 benign
b.gt LBB80_27
cond-branch
control-flow
c7KV:7155 benign
b.gt LBB80_28
cond-branch
control-flow
c7KV:7160 benign
b.gt LBB80_29
cond-branch
control-flow
c7KV:7165 benign
b.gt LBB80_30
cond-branch
control-flow
c7KV:7170 benign
b.gt LBB80_31
cond-branch
control-flow
c7KV:7175 benign
b.gt LBB80_32
cond-branch
control-flow
c7KV:7180 benign
b.gt LBB80_33
cond-branch
control-flow
c7KV:7185 benign
b.gt LBB80_34
cond-branch
control-flow
c7KV:7190 benign
b.gt LBB80_35
cond-branch
control-flow
c7KV:7195 benign
b.gt LBB80_36
cond-branch
control-flow
c7KV:7200 benign
b.gt LBB80_37
cond-branch
control-flow
c7KV:7205 benign
b.gt LBB80_38
cond-branch
control-flow
c7KV:7210 benign
b.gt LBB80_39
cond-branch
control-flow
c7KV:7215 benign
b.gt LBB80_40
cond-branch
control-flow
c7KV:7220 benign
b.lt LBB80_41
cond-branch
control-flow
c7KV:7225 benign
b.ge LBB80_43
cond-branch
control-flow
c7KV:7231 benign
lsl x9, x12, x9
var-shift
operand-timing
c7KV:7239 benign
cbnz x8, LBB80_4
cond-branch
control-flow
c7KV:7290 benign
b.le LBB80_6
cond-branch
control-flow
c7KV:7307 benign
b.le LBB80_7
cond-branch
control-flow
c7KV:7315 benign
b.le LBB80_8
cond-branch
control-flow
c7KV:7323 benign
b.le LBB80_9
cond-branch
control-flow
c7KV:7331 benign
b.le LBB80_10
cond-branch
control-flow
c7KV:7339 benign
b.le LBB80_11
cond-branch
control-flow
c7KV:7347 benign
b.le LBB80_12
cond-branch
control-flow
c7KV:7355 benign
b.le LBB80_13
cond-branch
control-flow
c7KV:7363 benign
b.le LBB80_14
cond-branch
control-flow
c7KV:7371 benign
b.le LBB80_15
cond-branch
control-flow
c7KV:7379 benign
b.le LBB80_16
cond-branch
control-flow
c7KV:7387 benign
b.le LBB80_17
cond-branch
control-flow
c7KV:7395 benign
b.le LBB80_18
cond-branch
control-flow
c7KV:7403 benign
b.le LBB80_19
cond-branch
control-flow
c7KV:7411 benign
b.le LBB80_20
cond-branch
control-flow
c7KV:7419 benign
b.ge LBB80_21
cond-branch
control-flow
c7KV:7427 benign
b.eq LBB80_45
cond-branch
control-flow
c7KV:7480 benign
lsl x15, x11, x12
var-shift
operand-timing
c7Wu:8269 benign
lsr x16, x8, x13
var-shift
operand-timing
c7Wu:8270 benign
lsl x9, x9, x12
var-shift
operand-timing
c7Wu:8277 benign
lsl x16, x16, x12
var-shift
operand-timing
c7Wu:8280 benign
lsr x11, x11, x13
var-shift
operand-timing
c7Wu:8281 benign
lsl x10, x14, x10
var-shift
operand-timing
c7Wu:8282 benign
lsr x12, x15, x13
var-shift
operand-timing
c7Wu:8283 benign
lsl x15, x11, x12
var-shift
operand-timing
c7Ya:6361 benign
lsr x16, x8, x13
var-shift
operand-timing
c7Ya:6362 benign
lsl x9, x9, x12
var-shift
operand-timing
c7Ya:6369 benign
lsl x16, x16, x12
var-shift
operand-timing
c7Ya:6372 benign
lsr x11, x11, x13
var-shift
operand-timing
c7Ya:6373 benign
lsl x10, x14, x10
var-shift
operand-timing
c7Ya:6374 benign
lsr x12, x15, x13
var-shift
operand-timing
c7Ya:6375 benign
x86_64
jne .LBB69_1
cond-branch
control-flow
c7CO:6014 benign
jge .LBB75_1
cond-branch
control-flow
c7F4:6492 benign
je .LBB75_58
cond-branch
control-flow
c7F4:6506 benign
jle .LBB75_4
cond-branch
control-flow
c7F4:6509 benign
jg .LBB75_55
cond-branch
control-flow
c7F4:6522 benign
jg .LBB75_54
cond-branch
control-flow
c7F4:6526 benign
jg .LBB75_53
cond-branch
control-flow
c7F4:6530 benign
jg .LBB75_52
cond-branch
control-flow
c7F4:6534 benign
jg .LBB75_51
cond-branch
control-flow
c7F4:6538 benign
jg .LBB75_50
cond-branch
control-flow
c7F4:6542 benign
jg .LBB75_49
cond-branch
control-flow
c7F4:6546 benign
jg .LBB75_48
cond-branch
control-flow
c7F4:6550 benign
jg .LBB75_47
cond-branch
control-flow
c7F4:6554 benign
jg .LBB75_46
cond-branch
control-flow
c7F4:6558 benign
jg .LBB75_45
cond-branch
control-flow
c7F4:6562 benign
jg .LBB75_44
cond-branch
control-flow
c7F4:6566 benign
jg .LBB75_43
cond-branch
control-flow
c7F4:6570 benign
jg .LBB75_42
cond-branch
control-flow
c7F4:6574 benign
jl .LBB75_40
cond-branch
control-flow
c7F4:6578 benign
jge .LBB75_37
cond-branch
control-flow
c7F4:6581 benign
shlq %cl, %rax
var-shift
operand-timing
c7F4:6663 benign
jne .LBB75_3
cond-branch
control-flow
c7F4:6682 benign
jge .LBB80_2
cond-branch
control-flow
c7Mt:7902 benign
je .LBB80_59
cond-branch
control-flow
c7Mt:7936 benign
jle .LBB80_5
cond-branch
control-flow
c7Mt:7939 benign
jg .LBB80_56
cond-branch
control-flow
c7Mt:7952 benign
jg .LBB80_55
cond-branch
control-flow
c7Mt:7956 benign
jg .LBB80_54
cond-branch
control-flow
c7Mt:7960 benign
jg .LBB80_53
cond-branch
control-flow
c7Mt:7964 benign
jg .LBB80_52
cond-branch
control-flow
c7Mt:7968 benign
jg .LBB80_51
cond-branch
control-flow
c7Mt:7972 benign
jg .LBB80_50
cond-branch
control-flow
c7Mt:7976 benign
jg .LBB80_49
cond-branch
control-flow
c7Mt:7980 benign
jg .LBB80_48
cond-branch
control-flow
c7Mt:7984 benign
jg .LBB80_47
cond-branch
control-flow
c7Mt:7988 benign
jg .LBB80_46
cond-branch
control-flow
c7Mt:7992 benign
jg .LBB80_45
cond-branch
control-flow
c7Mt:7996 benign
jg .LBB80_44
cond-branch
control-flow
c7Mt:8000 benign
jg .LBB80_43
cond-branch
control-flow
c7Mt:8004 benign
jl .LBB80_41
cond-branch
control-flow
c7Mt:8008 benign
jge .LBB80_38
cond-branch
control-flow
c7Mt:8011 benign
shlq %cl, %rax
var-shift
operand-timing
c7Mt:8018 benign
shlq %cl, %rax
var-shift
operand-timing
c7Y2:9103 benign
shrq %cl, %rdx
var-shift
operand-timing
c7Y2:9106 benign
shlq %cl, %rdx
var-shift
operand-timing
c7Y2:9114 benign
shrq %cl, %rax
var-shift
operand-timing
c7Y2:9116 benign
shlq %cl, %rax
var-shift
operand-timing
c7Y2:9122 benign
shlq %cl, %rax
var-shift
operand-timing
c7ZI:7037 benign
shrq %cl, %rdx
var-shift
operand-timing
c7ZI:7040 benign
shlq %cl, %rdx
var-shift
operand-timing
c7ZI:7048 benign
shrq %cl, %rax
var-shift
operand-timing
c7ZI:7050 benign
shlq %cl, %rax
var-shift
operand-timing
c7ZI:7056 benign
riscv64
bne s7, a0, .LBB68_5
cond-branch
control-flow
$wmac:5844 input validation
bne a0, a1, .LBB69_3
cond-branch
control-flow
c7CO:5890 benign
bge a2, a1, .LBB75_21
cond-branch
control-flow
c7F4:6357 benign
beq a0, zero, .LBB75_22
cond-branch
control-flow
c7F4:6371 benign
bge a1, a0, .LBB75_23
cond-branch
control-flow
c7F4:6375 benign
blt a1, a0, .LBB75_24
cond-branch
control-flow
c7F4:6385 benign
blt a1, a0, .LBB75_25
cond-branch
control-flow
c7F4:6390 benign
blt a1, a0, .LBB75_26
cond-branch
control-flow
c7F4:6395 benign
blt a1, a0, .LBB75_27
cond-branch
control-flow
c7F4:6400 benign
blt a1, a0, .LBB75_28
cond-branch
control-flow
c7F4:6405 benign
blt a1, a0, .LBB75_29
cond-branch
control-flow
c7F4:6410 benign
blt zero, a0, .LBB75_30
cond-branch
control-flow
c7F4:6414 benign
blt a1, a0, .LBB75_31
cond-branch
control-flow
c7F4:6419 benign
blt a1, a0, .LBB75_32
cond-branch
control-flow
c7F4:6424 benign
blt a1, a0, .LBB75_33
cond-branch
control-flow
c7F4:6429 benign
blt a1, a0, .LBB75_34
cond-branch
control-flow
c7F4:6434 benign
blt a1, a0, .LBB75_35
cond-branch
control-flow
c7F4:6439 benign
blt a1, a0, .LBB75_36
cond-branch
control-flow
c7F4:6444 benign
blt a1, a0, .LBB75_37
cond-branch
control-flow
c7F4:6449 benign
blt a1, a0, .LBB75_38
cond-branch
control-flow
c7F4:6454 benign
blt a0, a1, .LBB75_39
cond-branch
control-flow
c7F4:6459 benign
bge a0, a1, .LBB75_41
cond-branch
control-flow
c7F4:6463 benign
sll a1, a1, a2
var-shift
operand-timing
c7F4:6539 benign
bne a0, zero, .LBB75_2
cond-branch
control-flow
c7F4:6559 benign
bge a1, a0, .LBB75_4
cond-branch
control-flow
c7F4:6584 benign
bge a1, a0, .LBB75_5
cond-branch
control-flow
c7F4:6592 benign
bge a1, a0, .LBB75_6
cond-branch
control-flow
c7F4:6600 benign
bge a1, a0, .LBB75_7
cond-branch
control-flow
c7F4:6608 benign
bge a1, a0, .LBB75_8
cond-branch
control-flow
c7F4:6616 benign
bge a1, a0, .LBB75_9
cond-branch
control-flow
c7F4:6624 benign
bge zero, a0, .LBB75_10
cond-branch
control-flow
c7F4:6631 benign
bge a1, a0, .LBB75_11
cond-branch
control-flow
c7F4:6639 benign
bge a1, a0, .LBB75_12
cond-branch
control-flow
c7F4:6647 benign
bge a1, a0, .LBB75_13
cond-branch
control-flow
c7F4:6655 benign
bge a1, a0, .LBB75_14
cond-branch
control-flow
c7F4:6663 benign
bge a1, a0, .LBB75_15
cond-branch
control-flow
c7F4:6671 benign
bge a1, a0, .LBB75_16
cond-branch
control-flow
c7F4:6679 benign
bge a1, a0, .LBB75_17
cond-branch
control-flow
c7F4:6687 benign
bge a1, a0, .LBB75_18
cond-branch
control-flow
c7F4:6695 benign
bge a0, a1, .LBB75_19
cond-branch
control-flow
c7F4:6703 benign
bge a0, a1, .LBB80_23
cond-branch
control-flow
c7Mt:7763 benign
beq a0, zero, .LBB80_24
cond-branch
control-flow
c7Mt:7778 benign
bge a1, a0, .LBB80_25
cond-branch
control-flow
c7Mt:7782 benign
blt a1, a0, .LBB80_26
cond-branch
control-flow
c7Mt:7792 benign
blt a1, a0, .LBB80_27
cond-branch
control-flow
c7Mt:7797 benign
blt a1, a0, .LBB80_28
cond-branch
control-flow
c7Mt:7802 benign
blt a1, a0, .LBB80_29
cond-branch
control-flow
c7Mt:7807 benign
blt a1, a0, .LBB80_30
cond-branch
control-flow
c7Mt:7812 benign
blt a1, a0, .LBB80_31
cond-branch
control-flow
c7Mt:7817 benign
blt zero, a0, .LBB80_32
cond-branch
control-flow
c7Mt:7821 benign
blt a1, a0, .LBB80_33
cond-branch
control-flow
c7Mt:7826 benign
blt a1, a0, .LBB80_34
cond-branch
control-flow
c7Mt:7831 benign
blt a1, a0, .LBB80_35
cond-branch
control-flow
c7Mt:7836 benign
blt a1, a0, .LBB80_36
cond-branch
control-flow
c7Mt:7841 benign
blt a1, a0, .LBB80_37
cond-branch
control-flow
c7Mt:7846 benign
blt a1, a0, .LBB80_38
cond-branch
control-flow
c7Mt:7851 benign
blt a1, a0, .LBB80_39
cond-branch
control-flow
c7Mt:7856 benign
blt a1, a0, .LBB80_40
cond-branch
control-flow
c7Mt:7861 benign
blt a0, a1, .LBB80_41
cond-branch
control-flow
c7Mt:7866 benign
bge a0, a1, .LBB80_43
cond-branch
control-flow
c7Mt:7870 benign
sll a1, a2, a1
var-shift
operand-timing
c7Mt:7877 benign
bne a0, zero, .LBB80_4
cond-branch
control-flow
c7Mt:7915 benign
bge a1, a0, .LBB80_6
cond-branch
control-flow
c7Mt:7937 benign
bge a1, a0, .LBB80_7
cond-branch
control-flow
c7Mt:7945 benign
bge a1, a0, .LBB80_8
cond-branch
control-flow
c7Mt:7953 benign
bge a1, a0, .LBB80_9
cond-branch
control-flow
c7Mt:7961 benign
bge a1, a0, .LBB80_10
cond-branch
control-flow
c7Mt:7969 benign
bge a1, a0, .LBB80_11
cond-branch
control-flow
c7Mt:7977 benign
bge zero, a0, .LBB80_12
cond-branch
control-flow
c7Mt:7984 benign
bge a1, a0, .LBB80_13
cond-branch
control-flow
c7Mt:7992 benign
bge a1, a0, .LBB80_14
cond-branch
control-flow
c7Mt:8000 benign
bge a1, a0, .LBB80_15
cond-branch
control-flow
c7Mt:8008 benign
bge a1, a0, .LBB80_16
cond-branch
control-flow
c7Mt:8016 benign
bge a1, a0, .LBB80_17
cond-branch
control-flow
c7Mt:8024 benign
bge a1, a0, .LBB80_18
cond-branch
control-flow
c7Mt:8032 benign
bge a1, a0, .LBB80_19
cond-branch
control-flow
c7Mt:8040 benign
bge a1, a0, .LBB80_20
cond-branch
control-flow
c7Mt:8048 benign
bge a0, a1, .LBB80_21
cond-branch
control-flow
c7Mt:8056 benign
sll a0, a2, a3
var-shift
operand-timing
c7Y2:8953 benign
srl a5, a1, a4
var-shift
operand-timing
c7Y2:8954 benign
sll a0, a5, a3
var-shift
operand-timing
c7Y2:8960 benign
srl a2, a2, a4
var-shift
operand-timing
c7Y2:8961 benign
sll a1, a1, a3
var-shift
operand-timing
c7Y2:8967 benign
srl a2, a5, a4
var-shift
operand-timing
c7Y2:8968 benign
sll a1, a5, a3
var-shift
operand-timing
c7Y2:8971 benign
sll a0, a2, a3
var-shift
operand-timing
c7ZI:6905 benign
srl a5, a1, a4
var-shift
operand-timing
c7ZI:6906 benign
sll a0, a5, a3
var-shift
operand-timing
c7ZI:6912 benign
srl a2, a2, a4
var-shift
operand-timing
c7ZI:6913 benign
sll a1, a1, a3
var-shift
operand-timing
c7ZI:6919 benign
srl a2, a5, a4
var-shift
operand-timing
c7ZI:6920 benign
sll a1, a5, a3
var-shift
operand-timing
c7ZI:6923 benign
censor50000 pairs · α=1.0e-6 · batch 1
test cases
mac (key fix-vs-random) class A computes the MAC with a fixed 32-byte one-time key, class B with a fresh random key per draw; the 245-byte message (15 full blocks plus a 5-byte final chunk) stays fixed in both classes, per-draw buffer copies keep allocation and cache behaviour symmetric, and only key content differs
host meter result p effect (mean/pair) jitter clip scale clipped
mac (key fix-vs-random)
aarch64-darwin wall 0.615 [-13, 4.47] ns 34% 84 ns 10/50000 at 16c
x86_64-linux wall 0.925 [-233, 78] ns 25% 1460 ns 65/50000 at 16c
x86_64-linux instructions 0.511 [-11, 33] instr 0.0% 210 instr 10/50000 at 16c
x86_64-linux cycles 0.423 [-306, 919] cyc 3.3% 5762 cyc 24/50000 at 16c
mac (key fix-vs-random)aarch64-darwin
wall
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.615
mean per-pair effect [-13, 4.47] ns · clip scale c=84 ns · clipped 10/50000 at 16c · batch 1 · baseline med 125 iqr 42 (34% jitter)
mac (key fix-vs-random)x86_64-linux
wall
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.925
mean per-pair effect [-233, 78] ns · clip scale c=1460 ns · clipped 65/50000 at 16c · batch 1 · baseline med 610 iqr 150 (25% jitter)
2 further meter panels
mac (key fix-vs-random)x86_64-linux
instructions
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.511
mean per-pair effect [-11, 33] instr · clip scale c=210 instr · clipped 10/50000 at 16c · batch 1 · baseline med 6126 iqr 0.00 (0.0% jitter)
mac (key fix-vs-random)x86_64-linux
cycles
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.423
mean per-pair effect [-306, 919] cyc · clip scale c=5762 cyc · clipped 24/50000 at 16c · batch 1 · baseline med 4823 iqr 160 (3.3% jitter)

poly1305_mac_arm

poly1305_mac_arm (cbits/poly1305_arm.c)sensitive: key (256-bit one-time key)
substratumcc
isa result symbols walked instructions flagged
aarch64 3 13
class assessment note aarch64
cond-branch
control-flow
benign
block control on the public message length: the 256-byte NEON engagement threshold, the four-block and single-block loop entries and latches, and the final partial-chunk test
×5
reg-index
memory-address
benign
message and padding addressing on the public block cursor: paired block loads at sequential public offsets from the message base, and the padding terminator store at the public remainder index
×7
cond-branch
control-flow
benign
stack-protector epilogue check on the per-process __stack_chk_guard canary (independent of key and message)
×1
early-return-guard
← load (approximate)
complete fact list — aarch64 ×13
aarch64
b.lo LBB0_3
cond-branch
control-flow
_poly1305_mac_arm:66 benign
ldp w10, w11, [x17]
reg-index
memory-address
_poly1305_mac_arm:250 benign
ldp w12, w15, [x17, #8]
reg-index
memory-address
_poly1305_mac_arm:251 benign
ldp w12, w11, [x17, #16]
reg-index
memory-address
_poly1305_mac_arm:259 benign
ldp w16, w3, [x17, #24]
reg-index
memory-address
_poly1305_mac_arm:260 benign
b.ls LBB0_2
cond-branch
control-flow
_poly1305_mac_arm:407 benign
b.ls LBB0_6
cond-branch
control-flow
_poly1305_mac_arm:419 benign
ldp w17, w0, [x16]
reg-index
memory-address
_poly1305_mac_arm:437 benign
ldp w3, w16, [x16, #8]
reg-index
memory-address
_poly1305_mac_arm:438 benign
b.ls LBB0_7
cond-branch
control-flow
_poly1305_mac_arm:498 benign
b.ls LBB0_10
cond-branch
control-flow
_poly1305_mac_arm:501 benign
strb w8, [x9, x21]
reg-index
memory-address
_poly1305_mac_arm:511 benign
b.ne LBB0_12
cond-branch
control-flow
_poly1305_mac_arm:640 benign
censor50000 pairs · α=1.0e-6 · batch 1
test cases
mac (key fix-vs-random, 320 B) class A computes the MAC through the shipped ARM dispatch with a fixed 32-byte one-time key, class B with a fresh random key per draw; the 320-byte message (twenty exact blocks, engaging the kernel's NEON 4-way path for five iterations with no scalar tail or partial block) stays fixed in both classes, per-draw buffer copies keep allocation and cache behaviour symmetric, and only key content differs
host meter result p effect (mean/pair) jitter clip scale clipped
mac (key fix-vs-random, 320 B)
aarch64-darwin wall 0.006 [-13, 4.47] ns 25% 84 ns 13/50000 at 16c
mac (key fix-vs-random, 320 B)aarch64-darwin
wall
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.006
mean per-pair effect [-13, 4.47] ns · clip scale c=84 ns · clipped 13/50000 at 16c · batch 1 · baseline med 166 iqr 42 (25% jitter)

(==) (MAC)

Crypto.MAC.Poly1305.Eq MAC ((==))sensitive: tag bytes; mismatch position
substratumllvm
isa result symbols walked instructions flagged
aarch64 7 6
x86_64 6 6
riscv64 7 6
class assessment note aarch64 x86_64 riscv64
cond-branch
control-flow
input validation
public unequal-length MAC rejection (False before any tag byte is read)
×1
early-return-guard
← entry (R4) + load (Sp frame slot)
×1
← entry (Sp) + entry (R4)
×1
← entry (R4) + load (Sp frame slot)
cond-branch
control-flow
benign
post-barrier dispatch on the tag verdict after the full XOR/OR byte fold (mismatch position is collapsed into the barrier-routed accumulator before any branch; only the published accept/reject bit steers control)
×1
← entry (R1)
×1
← entry (R1)
×1
← entry (R1)
cond-branch
control-flow
benign
zero-trip entry guard and per-byte latch of the comparison fold, both on the public MAC length
×2
×2
← entry + load (approximate)
×2
← load
reg-index
memory-address
benign
tag-byte loads addressed by the sequential fold counter (every position visited exactly once regardless of tag contents)
×2
loop-latch, loop-exit, early-return-guard, chained-guard
address-base ← load
address-index ← load
×2
loop-latch, loop-exit
address-base ← load
address-index ← load
×2
loop-latch, loop-exit, chained-guard
address-base ← load
address-index ← load
complete fact list — aarch64 ×6 · x86_64 ×6 · riscv64 ×6
aarch64
b.eq LBB11_2
cond-branch
control-flow
$w$c==:429 input validation
b.eq LBB11_4
cond-branch
control-flow
$w$c==:445 benign
ldrb w8, [x8, x9]
reg-index
memory-address
$w$c==:451 benign
ldrb w10, [x10, x9]
reg-index
memory-address
$w$c==:452 benign
b.ne LBB11_3
cond-branch
control-flow
$w$c==:463 benign
b.eq LBB12_2
cond-branch
control-flow
c5iA:487 benign
x86_64
je .LBB11_1
cond-branch
control-flow
$w$c==:445 input validation
je .LBB11_4
cond-branch
control-flow
$w$c==:462 benign
movzbl (%rax,%rcx,1), %eax
reg-index
memory-address
$w$c==:468 benign
movzbl (%rdx,%rcx,1), %edx
reg-index
memory-address
$w$c==:471 benign
jne .LBB11_3
cond-branch
control-flow
$w$c==:481 benign
je .LBB12_2
cond-branch
control-flow
c5iM:502 benign
riscv64
beq s7, a0, .LBB11_2
cond-branch
control-flow
$w$c==:430 input validation
beq a0, a1, .LBB11_4
cond-branch
control-flow
$w$c==:447 benign
lbu a0, 0(a0)
reg-index
memory-address
$w$c==:454 benign
lbu a2, 0(a2)
reg-index
memory-address
$w$c==:456 benign
bne a0, a1, .LBB11_3
cond-branch
control-flow
$w$c==:467 benign
beq a0, zero, .LBB12_2
cond-branch
control-flow
c5iM:489 benign
censor50000 pairs · α=1.0e-6 · batch 1
test cases
tag mismatch class A flips byte 0 of a freshly computed tag, class B flips byte 15 (opposite 64-bit halves of the tag); fresh random 32-byte key and 256-byte message per draw, lengths fixed, every comparison rejects, and only the mismatch position differs between classes
host meter result p effect (mean/pair) jitter clip scale clipped
tag mismatch
aarch64-darwin wall 0.852 [-13, 4.47] ns 2.4% 84 ns 3/50000 at 16c
x86_64-linux wall 0.089 [-32, 96] ns 169% 600 ns 40/50000 at 16c
x86_64-linux instructions 0.472 [-0.16, 0.27] instr 0.0% 1.00 instr 19523/50000 at 16c
x86_64-linux cycles 0.818 [-390, 130] cyc 15% 2448 cyc 0/50000 at 16c
tag mismatchaarch64-darwin
wall
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.852
mean per-pair effect [-13, 4.47] ns · clip scale c=84 ns · clipped 3/50000 at 16c · batch 1 · baseline med 42 iqr 1.00 (2.4% jitter)
tag mismatchx86_64-linux
wall
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.089
mean per-pair effect [-32, 96] ns · clip scale c=600 ns · clipped 40/50000 at 16c · batch 1 · baseline med 130 iqr 220 (169% jitter)
tag mismatchx86_64-linux
instructions
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.472
mean per-pair effect [-0.16, 0.27] instr · clip scale c=1.00 instr · clipped 19523/50000 at 16c · batch 1 · baseline med 540 iqr 0.00 (0.0% jitter)
high clipping (39% of pairs sat at bound)
1 further meter panel
tag mismatchx86_64-linux
cycles
log(1/α) 0 0
no leak detected · 50000 pairs · α=1.0e-6 · p=0.818
mean per-pair effect [-390, 130] cyc · clip scale c=2448 cyc · clipped 0/50000 at 16c · batch 1 · baseline med 1618 iqr 235 (15% jitter)
analysis bounds
aarch64
lines parsed
9528 (7446 instruction lines)
unstructured
29 instruction lines the decoder did not structure: sturb ×29
memory unmodelled
29 memory-capable instructions with no modelled effect: sturb ×29
control-flow graph
141 functions, 0 with a reachable unknown successor
facts by disposition
active ×232, suppressed ×139
fact operands
371 of 371 facts with a modelled subject, 0 unmodelled, 0 with none by design; 375 subjects: address-base ×4, address-index ×4, branch-condition ×262, indirect-target ×73, shift-count ×32
operand chains
exact ×353, approximate ×22 — an approximate chain bounds what the subject's provenance establishes, and is marked as such beside the finding
walk boundary · mac
38 edges — indirect-call ×20, unresolved-enter ×11, external-callee ×7; at: _stg_gc_noregs ×3, _stg_gc_unpt_r1 ×1, _stg_keepAlivezh ×1, ppad-poly1305:Crypto.MAC.Poly1305.Arm.$wmac_info ×1, _stg_newPinnedByteArrayzh ×1
walk boundary · poly1305_mac_arm
2 edges — external-callee ×2; at: ___memcpy_chk ×1, ___stack_chk_fail ×1
walk boundary · (==) (MAC)
7 edges — indirect-call ×5, unresolved-enter ×1, external-callee ×1; at: ppad-poly1305:Data.Barrier.$wbarrier_info ×1
riscv64
lines parsed
10398 (8631 instruction lines)
unstructured
0 instruction lines the decoder did not structure
memory unmodelled
0 memory-capable instructions with no modelled effect
control-flow graph
268 functions, 57 with a reachable unknown successor
facts by disposition
active ×233, suppressed ×138, contract-satisfied ×2
fact operands
373 of 373 facts with a modelled subject, 0 unmodelled, 0 with none by design; 377 subjects: address-base ×4, address-index ×4, branch-condition ×262, indirect-target ×73, shift-count ×32, work-count ×2
operand chains
exact ×369, approximate ×8 — an approximate chain bounds what the subject's provenance establishes, and is marked as such beside the finding
walk boundary · mac
49 edges — indirect-tail ×20, unresolved-enter ×14, unresolved-edge-target ×8, external-callee ×7; at: ghc-internal:GHC.Internal.ForeignPtr.PlainPtr_con_info ×3, bytestring:Data.ByteString.Internal.Type.BS_con_info ×3, stg_gc_noregs ×3, ghc-internal:GHC.Internal.Maybe.Just_con_info ×2, stg_gc_unpt_r1 ×1, stg_keepAlivezh ×1, ppad-poly1305:Crypto.MAC.Poly1305.Arm.$wmac_info ×1, stg_newPinnedByteArrayzh ×1
no structural role · mac
76 sites (incomplete-cfg ×76, incomplete-side-region ×74)
walk boundary · (==) (MAC)
8 edges — indirect-tail ×5, unresolved-enter ×2, external-callee ×1; at: ppad-poly1305:Data.Barrier.$wbarrier_info ×1
no structural role · (==) (MAC)
1 site (incomplete-cfg ×1, incomplete-side-region ×1)
x86_64
lines parsed
10562 (8650 instruction lines)
unstructured
0 instruction lines the decoder did not structure
memory unmodelled
0 memory-capable instructions with no modelled effect
control-flow graph
134 functions, 17 with a reachable unknown successor
facts by disposition
active ×129, suppressed ×232
fact operands
361 of 361 facts with a modelled subject, 0 unmodelled, 0 with none by design; 365 subjects: address-base ×4, address-index ×4, branch-condition ×260, indirect-target ×73, shift-count ×24
operand chains
exact ×179, approximate ×186 — an approximate chain bounds what the subject's provenance establishes, and is marked as such beside the finding
walk boundary · mac
41 edges — indirect-tail ×20, unresolved-enter ×14, external-callee ×7; at: stg_gc_noregs@PLT ×3, stg_gc_unpt_r1@PLT ×1, stg_keepAlivezh@PLT ×1, ppad-poly1305:Crypto.MAC.Poly1305.Arm.$wmac_info ×1, stg_newPinnedByteArrayzh@PLT ×1
walk boundary · (==) (MAC)
9 edges — indirect-tail ×5, unresolved-enter ×3, external-callee ×1; at: ppad-poly1305:Data.Barrier.$wbarrier_info ×1
no structural role · (==) (MAC)
1 site (incomplete-cfg ×1, incomplete-side-region ×1)
provenance
target
ppad-poly1305 0.4.6 (ed28a72)
substratum
0.3.7 (2d3b67b)
censor
0.4.4 (9b550af)
elenchus
(appraise) moonshotai/kimi-k3
(dissent) gpt-5.6-sol
(falsify) claude-fable-5
(distill) claude-fable-5
source
git.ppad.tech/poly1305
seed
0x5eed5eed5eed5eed
censor config
alpha=1.000000e-6, budget=50000, warmup=500, batch=per-case
run environments
aarch64-darwin · wall
Apple M4 (10 cores) · darwin 24.6.0 · 2026-08-08T14:01:39Z
x86_64-linux · cycles
AMD EPYC 7713 64-Core Processor (6 cores) · linux 6.18.33 · 2026-08-07T21:37:17Z
x86_64-linux · instructions
AMD EPYC 7713 64-Core Processor (6 cores) · linux 6.18.33 · 2026-08-07T21:36:56Z
x86_64-linux · wall
AMD EPYC 7713 64-Core Processor (6 cores) · linux 6.18.33 · 2026-08-07T21:37:46Z
run totals
aarch64-darwin · wall
3 cases · 150000 pairs · 0 reject · α=1.0e-6 · family α=3.0e-6
x86_64-linux · cycles
2 cases · 100000 pairs · 0 reject · α=1.0e-6 · family α=2.0e-6
x86_64-linux · instructions
2 cases · 100000 pairs · 0 reject · α=1.0e-6 · family α=2.0e-6
x86_64-linux · wall
2 cases · 100000 pairs · 0 reject · α=1.0e-6 · family α=2.0e-6
# substratum 0.3.7 (2d3b67b)
# toolchain: GHC 9.10.3, LLVM 19.1.7 (nix-pinned via flake)
# ppad-poly1305 v0.4.6 (ed28a72; lib source == v0.4.6 tag,
#   only cabal other-modules metadata differs)
substratum scan -i audit-poly1305/aarch64/asm/Poly1305.llvm.s --isa aarch64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/aarch64/asm/Barrier.llvm.s --isa aarch64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/aarch64/asm/Arm.llvm.s --isa aarch64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/aarch64/asm/Poly1305.llvm.s --isa aarch64 --runtime haskell --format json --why -s 'ppad-poly1305:Crypto.MAC.Poly1305:$fEqMAC_$c=='
substratum scan -i audit-poly1305/aarch64/asm/Poly1305.llvm.s --isa aarch64 --runtime haskell --format json --why -s 'ppad-poly1305:Crypto.MAC.Poly1305:mac'
# cbits: the ARM NEON kernel cbits/poly1305_arm.c ships in the
# same library but is compiled by the C toolchain, not GHC. The
# dump, whole-file scan, and rooted walk below present it as its
# own static lane (generic runtime, backend "cc").
# C compiler: clang 21.1.2 (nix clang-wrapper-21.1.2, the
#   devshell cc the shipped build uses), target
#   arm64-apple-darwin, apple-sdk 14.4. Codegen flags per the
#   cabal build (-optc-O2 -optc-march=armv8-a via GHC's driver):
cc -O2 -march=armv8-a -S cbits/poly1305_arm.c -o audit-poly1305/aarch64/asm/poly1305_arm.c.s
substratum scan -i audit-poly1305/aarch64/asm/poly1305_arm.c.s --isa aarch64 --runtime generic --format json --why --decisions --loops
substratum scan -i audit-poly1305/aarch64/asm/poly1305_arm.c.s --isa aarch64 --runtime generic --format json --why -s '_poly1305_mac_arm'
# substratum 0.3.7 (2d3b67b)
# toolchain: GHC 9.10.3, LLVM 19.1.7 (nix-pinned via flake)
# ppad-poly1305 v0.4.6 (ed28a72; lib source == v0.4.6 tag,
#   only cabal other-modules metadata differs)
substratum scan -i audit-poly1305/rv64/asm/Poly1305.llvm.s --isa riscv64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/rv64/asm/Barrier.llvm.s --isa riscv64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/rv64/asm/Arm.llvm.s --isa riscv64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/rv64/asm/Poly1305.llvm.s --isa riscv64 --runtime haskell --format json --why -s 'ppad-poly1305:Crypto.MAC.Poly1305:$fEqMAC_$c=='
substratum scan -i audit-poly1305/rv64/asm/Poly1305.llvm.s --isa riscv64 --runtime haskell --format json --why -s 'ppad-poly1305:Crypto.MAC.Poly1305:mac'
# substratum 0.3.7 (2d3b67b)
# toolchain: GHC 9.10.3, LLVM 19.1.7 (nix-pinned via flake)
# ppad-poly1305 v0.4.6 (ed28a72; lib source == v0.4.6 tag,
#   only cabal other-modules metadata differs)
substratum scan -i audit-poly1305/x86_64/asm/Poly1305.llvm.s --isa x86_64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/x86_64/asm/Barrier.llvm.s --isa x86_64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/x86_64/asm/Arm.llvm.s --isa x86_64 --runtime haskell --format json --why --decisions --loops
substratum scan -i audit-poly1305/x86_64/asm/Poly1305.llvm.s --isa x86_64 --runtime haskell --format json --why --no-demangle -s 'ppadzmpoly1305zm0zi4zi6zminplace_CryptoziMACziPoly1305_zdfEqMACzuzdczeze_info$def'
substratum scan -i audit-poly1305/x86_64/asm/Poly1305.llvm.s --isa x86_64 --runtime haskell --format json --why -s 'ppad-poly1305:Crypto.MAC.Poly1305:mac'
# censor 0.4.4 (9b550af)
# toolchain: GHC 9.10.3, LLVM 19.1.7 (nix-pinned via flake)
#
# aarch64-darwin (Apple M4), niced; wall only -- no userspace PMU.
nice -n 5 censor-poly --format plain wall \
  aarch64-darwin/wall/report.json
#
# x86_64-linux (AMD EPYC 7713), pinned and niced.
taskset -c 0 nice -n 5 censor-poly --format json instructions \
  x86_64-linux/instructions/report.json
taskset -c 0 nice -n 5 censor-poly --format json cycles \
  x86_64-linux/cycles/report.json
taskset -c 0 nice -n 5 censor-poly --format json wall \
  x86_64-linux/wall/report.json