Constant-Time Analysis: ppad-poly1305
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)
|
S✓C✓ | S✓C✓ | S✓C· |
|
poly1305_mac_arm
ARM NEON kernel backing mac on NEON-capable ARM hosts
|
S✓C✓ | S·C· | S·C· |
|
(==) (MAC)
constant-time tag comparison
|
S✓C✓ | S✓C– | S✓C· |
✓ no leak detected ✗ leak – qualified ? inconclusive · not run S = substratum C = censor
method
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.
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.
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).
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.
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)| 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
| 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 |
| 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 |
| 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 |
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 |
wall
wall
2 further meter panels
instructions
cycles
poly1305_mac_arm
poly1305_mac_arm (cbits/poly1305_arm.c)sensitive: key (256-bit one-time key)| 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
| 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 |
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 |
wall
(==) (MAC)
Crypto.MAC.Poly1305.Eq MAC ((==))sensitive: tag bytes; mismatch position| 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
| 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 |
| 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 |
| 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 |
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 |
wall
wall
instructions
1 further meter panel
cycles
analysis bounds
- 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
- 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)
- 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
- 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
- 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