Framing and IFAC
This section covers how packets are delimited on byte-stream interfaces (HDLC)
and how an interface authenticates and masks packets (IFAC). Both are normative
for wire interop on those media and proven by [VEC-HDLC] and [VEC-IFAC].
Medium specifics beyond framing (LoRa airtime, TCP particulars) are informative.
HDLC byte-stream framing
Byte-stream interfaces (TCP, serial, pipe) delimit packets with HDLC-style flags
and byte stuffing (Interfaces/TCPInterface.py:44-52,323):
FLAG = 0x7E
ESC = 0x7D
ESC_MASK = 0x20
frame = FLAG || escape(packet) || FLAG
escape: replace 0x7D -> 0x7D 0x5D, then 0x7E -> 0x7D 0x5E
A literal flag or escape byte inside the packet is replaced by the escape byte
followed by the original XORed with 0x20. [VEC-HDLC]: input 01 7E 02 7D 03
frames to 7e017d5e027d5d037e — leading flag, 01, escaped 7E→7D5E, 02,
escaped 7D→7D5D, 03, trailing flag. A receiver un-stuffs by reversing the
replacement between flags. (KISS interfaces use the analogous FEND/FESC framing.)
IFAC (interface access codes)
An interface configured with a passphrase derives a 64-byte IFAC identity and an
IFAC key, then authenticates and masks every packet (Transport.transmit,
Transport.py:1052-1087):
ifac = ifac_identity.sign(raw)[-ifac_size:]
mask = hkdf(length = len(raw) + ifac_size, derive_from = ifac, salt = ifac_key, context = None)
new_raw = (raw[0] | 0x80) || raw[1] || ifac || raw[2:]
masked[i] = new_raw[i] ^ mask[i] for i == 0 (then re-set bit 7), i == 1, and i > ifac_size+1
masked[i] = new_raw[i] for the ifac bytes (2 .. ifac_size+1, left unmasked)
The IFAC flag (header bit 7) is set, the ifac tag is inserted right after the
two header bytes, and everything except the tag itself is XOR-masked with the
HKDF stream. On receipt the interface reverses the mask, extracts the tag,
recomputes ifac_identity.sign(recovered_raw)[-ifac_size:], and drops the packet
on mismatch (Transport.inbound, Transport.py:1398-1435).
[VEC-IFAC] (ifac_size = 8) records the tag, the mask, the masked output
9f4a2cf485c1dfcea0…, the IFAC flag set in the masked header, and proves a full
mask/unmask roundtrip recovers the original packet and a matching tag
(unmask_roundtrip_ok = true). IFAC_MIN_SIZE = 1, and IFAC_SALT is a fixed
32-byte constant (Reticulum.py:146-147). An implementation sharing an interface
with Python peers MUST reproduce this masking exactly or its packets are dropped.