include/qrnsp_jitter.h
/*
* QR-NSP Volcanic Edition — Temporal Jitter Shaping
* Module 4: Timing-based covert channel
*
* Encodes binary data into the inter-packet arrival time (IPAT) of
* UDP datagrams. This is a SECOND steganographic channel, orthogonal
* to Module 3's PADDING injection. It works even when:
* - PADDING regions are too small or absent (short-header 1-RTT packets)
* - Packet payloads are fully encrypted and unmodifiable
* - Only packet timing is under our control
*
* Encoding: Spread-spectrum On-Off Keying (SS-OOK)
* bit 0 → inter-packet delay T_base + jitter
* bit 1 → inter-packet delay T_base + T_delta + jitter
* jitter ~ N(0, σ²) shaped to match natural network variance
*
* Stealth properties:
* - T_base and T_delta chosen so both bins overlap the natural IPAT
* distribution of the cover traffic (e.g., video streaming)
* - Added Gaussian noise makes individual delays indistinguishable
* - Only statistical analysis over many packets can detect the channel,
* and the spread-spectrum chipping makes that analysis expensive
*
* Bandwidth: ~10-100 bits/second (low but sufficient for key exchange,
* signaling, or short messages when PADDING channel is unavailable)
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#ifndef QRNSP_JITTER_H
#define QRNSP_JITTER_H
#include <stdint.h>
#include <stddef.h>
/* ─────────────────────────────────────────────
* Configuration
* ───────────────────────────────────────────── */
/* Timing parameters (microseconds) */
#define JITTER_T_BASE_US 5000 /* Base inter-packet delay: 5ms */
#define JITTER_T_DELTA_US 2000 /* Extra delay for bit=1: +2ms */
#define JITTER_SIGMA_US 800 /* Gaussian noise σ: 0.8ms */
/* Spread-spectrum chipping */
#define JITTER_CHIPS_PER_BIT 8 /* Chips per data bit (redundancy) */
#define JITTER_CHIP_SEQ_LEN 127 /* Gold code length (2^7 - 1) */
/* Synchronization preamble */
#define JITTER_PREAMBLE_BITS 16 /* Barker-13 + 3 guard bits */
#define JITTER_PREAMBLE_CHIPS (JITTER_PREAMBLE_BITS * JITTER_CHIPS_PER_BIT)
/* Manchester encoding doubles bit count but provides clock recovery */
#define JITTER_USE_MANCHESTER 1
/* Forward Error Correction */
#define JITTER_FEC_RATE_NUM 1 /* Rate 1/3 repetition code */
#define JITTER_FEC_RATE_DEN 3
/* Maximum payload (pre-FEC, pre-Manchester) */
#define JITTER_MAX_PAYLOAD 64 /* 64 bytes = 512 bits */
/* With Manchester + FEC + chipping:
* 512 bits × 2 (Manchester) × 3 (FEC) × 8 (chips) = 24576 chips
* At ~5ms/chip → ~123 seconds for 64 bytes
* Practical: use for signaling and short keys, not bulk data
*/
/* ─────────────────────────────────────────────
* State
* ───────────────────────────────────────────── */
typedef enum {
JITTER_ROLE_TX,
JITTER_ROLE_RX
} jitter_role_t;
typedef enum {
JITTER_STATE_IDLE,
JITTER_STATE_PREAMBLE, /* Sending/detecting preamble */
JITTER_STATE_DATA, /* Transmitting/receiving data bits */
JITTER_STATE_COMPLETE, /* Transfer finished */
JITTER_STATE_ERROR
} jitter_state_t;
/* Transmitter context */
typedef struct {
jitter_state_t state;
/* Data to transmit (after FEC + Manchester encoding) */
uint8_t chip_stream[8192]; /* Encoded chip sequence */
uint32_t chip_count; /* Total chips to send */
uint32_t chip_index; /* Current position */
/* Timing */
uint64_t last_tx_ns; /* Timestamp of last packet sent */
uint64_t next_tx_ns; /* Scheduled time for next packet */
/* Spread spectrum */
uint8_t gold_code[JITTER_CHIP_SEQ_LEN]; /* PN sequence */
uint32_t gold_phase; /* Current phase in Gold code */
/* PRNG for Gaussian noise (Box-Muller) */
uint64_t rng_state[2]; /* xorshift128+ state */
int has_spare; /* Box-Muller spare available */
double spare_val; /* Cached Gaussian sample */
/* Stats */
uint64_t packets_sent;
uint64_t bits_encoded;
} jitter_tx_t;
/* Receiver context */
typedef struct {
jitter_state_t state;
/* Arrival time buffer for correlation */
uint64_t arrival_times[32768]; /* Ring buffer of packet timestamps */
uint32_t arrival_head;
uint32_t arrival_count;
/* IPAT (inter-packet arrival time) samples */
int64_t ipat_samples[16384]; /* Computed IPATs in nanoseconds */
uint32_t ipat_count;
/* Preamble detection */
double correlation_buf[256];
int preamble_detected;
uint32_t preamble_offset; /* IPAT index where preamble starts */
/* Decoded chips → bits */
uint8_t raw_chips[8192];
uint32_t raw_chip_count;
/* Despread + FEC decoded data */
uint8_t decoded_data[JITTER_MAX_PAYLOAD];
uint32_t decoded_len;
/* Spread spectrum */
uint8_t gold_code[JITTER_CHIP_SEQ_LEN];
/* Timing reference */
double estimated_t_base; /* Estimated base delay */
double estimated_t_delta; /* Estimated delta */
double estimated_sigma; /* Estimated jitter */
/* Stats */
uint64_t packets_received;
double bit_error_rate;
} jitter_rx_t;
/* ─────────────────────────────────────────────
* TX API
* ───────────────────────────────────────────── */
/*
* Initialize transmitter with shared secret (for Gold code seed).
*/
int jitter_tx_init(jitter_tx_t *tx, const uint8_t seed[32]);
/*
* Load payload for transmission.
* Applies FEC → Manchester → spread-spectrum chipping.
* After this call, use jitter_tx_next_delay() in the packet send loop.
*/
int jitter_tx_load(jitter_tx_t *tx,
const uint8_t *payload, size_t len);
/*
* Get the delay (in nanoseconds) before sending the next packet.
* Returns 0 when transmission is complete.
*
* Usage in send loop:
* while ((delay = jitter_tx_next_delay(tx)) > 0) {
* nanosleep(delay);
* send_packet(cover_traffic);
* }
*/
uint64_t jitter_tx_next_delay(jitter_tx_t *tx);
/*
* Mark that a packet was actually sent (records true timestamp).
*/
void jitter_tx_packet_sent(jitter_tx_t *tx, uint64_t timestamp_ns);
/*
* Query progress: returns fraction complete [0.0, 1.0].
*/
double jitter_tx_progress(const jitter_tx_t *tx);
/* ─────────────────────────────────────────────
* RX API
* ───────────────────────────────────────────── */
/*
* Initialize receiver with shared secret (same seed as TX).
*/
int jitter_rx_init(jitter_rx_t *rx, const uint8_t seed[32]);
/*
* Feed a packet arrival timestamp to the receiver.
* Call this for every QUIC packet received.
*
* Returns:
* 0 — still collecting
* 1 — preamble detected, data reception in progress
* 2 — message fully decoded (read with jitter_rx_get_data)
* -1 — error
*/
int jitter_rx_feed(jitter_rx_t *rx, uint64_t timestamp_ns);
/*
* Retrieve decoded message after jitter_rx_feed returns 2.
*/
int jitter_rx_get_data(const jitter_rx_t *rx,
uint8_t *out, size_t out_cap,
size_t *out_len);
/*
* Reset receiver for next message.
*/
void jitter_rx_reset(jitter_rx_t *rx);
/* ─────────────────────────────────────────────
* Cleanup
* ───────────────────────────────────────────── */
void jitter_tx_destroy(jitter_tx_t *tx);
void jitter_rx_destroy(jitter_rx_t *rx);
#endif /* QRNSP_JITTER_H */