Skip to content

AlgorithmID/KeyID populate but carry bit-error values on weak encrypted frames — validate against the TIA-102 algid set #924

Description

@er-imagery

Environment: main (sha=738cae84, v0.7.3), includes #899 (encrypted webhook) and #916 (source-RID backfill). Single system (MMR, WACN BEE00), P25 Phase 1 + Phase 2, Airspy + RTL wideband, consuming the per-call broadcast.webhook sink into Oracle.

Summary

Follow-up to #813. algorithm_id / key_id now populate — that part is fixed, thank you. But on the completed-call webhook they populate with bit-error values on weak/partial encrypted frames: alongside the correct AES-256, the columns carry a near-uniform smear across the entire 0x00–0xFF space, with a distinct key_id for almost every garbage call. The fields are being surfaced straight from the voice-side crypto sync without any validity/confidence gate, so a mis-decoded frame emits a plausible-looking-but-wrong algid+key rather than nothing.

Same root-cause pattern as the source-RID backfill in #915/#916: a low-confidence voice-path decode is surfaced as if authoritative.

Evidence

126,329 completed-call webhook rows. Every row has algorithm_id and key_id populated (good). To separate real calls from ones whose crypto metadata is itself a mis-decode, I split on corroboration: whether the call's source_rid also appears in SDRTrunk's GRP_VCH_GRANT / affiliation log for the same system (a CRC-protected control-channel decode — trustworthy).

Corroborated encrypted calls — algorithm_id distribution:

algorithm_id calls distinct key_id
0x84 AES-256 2,250 18
0x00 (unresolved) 683 4
0x010xFF (every other value) non-standard ~4–22 each ≈ 1 key per call

The 0x84 row is the real system: AES-256, ~18 active key IDs — exactly what's expected on this network, and stable. Everything below it is noise. The tell is the tail: a roughly-flat ~4–22 calls at every remaining algid value, each with about as many distinct key_ids as calls. Real crypto has a small enumerated algid set and a bounded keyset; a uniform 256-wide spread with key≈call is decode error, not signalling.

Corroborated clear calls: algorithm_id = 0 for all 113,642 (GT reports 0, not the P25 0x80, for unencrypted — minor, but worth noting for consumers).

Uncorroborated encrypted calls (source_rid itself a bit-error, i.e. #915/#916 territory): 0x00 (347), 0x84 (190), then the same random tail — as expected, these are the lowest-confidence decodes and their algid is garbage too.

Ask

Validate the decoded AlgorithmID against the enumerated TIA-102.AACA algorithm-ID set (0x80 clear, 0x81 DES-OFB, 0x83 3DES, 0x84 AES-256, 0x9F DES-XL, 0xAA ADP, plus the Type-1 block) before surfacing it — and ideally gate algorithm_id/key_id on the same decode-confidence signal that #915 wants for source_rid. When the crypto sync doesn't decode cleanly, omit the fields (leave them zero-valued / omitempty) rather than emitting an out-of-set algid and a spurious key. A value outside the known set is provably wrong and is currently indistinguishable, downstream, from a real key.

Happy to share the raw split or run a targeted capture if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions