Skip to content

snaart/phantom_protocol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

607 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Phantom Protocol

crates.io docs.rs CI license MSRV

Post-quantum-secure L4/L6 universal transport framework in Rust.

Phantom Protocol is an SDK — a foundation for building secure networked products (VPN, messaging, …), not an end-user application. It gives applications an authenticated, confidential, post-quantum-secure byte pipe, pairing a hybrid classical-plus-PQ handshake (X25519 + ML-KEM-768 KEM, Ed25519 + ML-DSA-65 signatures — FIPS 203 / FIPS 204, pure Rust) with a transport layer: TCP / WebSocket sessions and a native reliable-UDP transport (PhantomUDP), plus WASI / embedded byte-stream framing. Cross-language bindings via UniFFI (Python, Swift, Kotlin, C); native WASM target; bare-metal EmbeddedLeg for no_std. (An optional TLS-over-TCP DPI-mimicry transport — mimicry feature — makes a flow look like HTTPS to passive DPI; anti-DPI obfuscation only, detectable by active probing — see Status & limitations.)

Pre-1.0 (0.2.2). Wire format may break between minors; SemVer kicks in at 1.0. 0 workspace warnings, 0 unsafe outside three audited opt-ins, MSRV Rust 1.93, CI green across the full cross-target matrix. See Status & limitations.

Install

Published on crates.io as phantom-protocol (the import path is phantom_protocol):

[dependencies]
phantom-protocol = "0.2"

or cargo add phantom-protocol. API docs: https://docs.rs/phantom-protocol.

Highlights

  • Hybrid post-quantum handshake — X25519 + ML-KEM-768 KEM, Ed25519 + ML-DSA-65 signatures. Both halves must verify. Pure-Rust RustCrypto primitives — no C bindings in the crypto path, so the full handshake compiles on native, mobile, and wasm32. (Bare-metal thumbv7em is std-gated to the framing transport only — see Status & limitations.)
  • 0-RTT resumption — AEAD-sealed early-data (≤ 16 KiB) folded into the single ClientHello, one-shot anti-replay via a consumed SessionCache ticket, best-effort fallback to a 1-RTT handshake when the ticket is unknown / expired or the blob fails to open.
  • Mid-session rekey — HKDF ratchet, REKEY flag + per-packet epoch.
  • TransportsPhantomSession runs an authenticated session over TCP, WebSocket, and a native reliable-UDP transport (PhantomUDP): connection-ID demux, SACK loss recovery + RFC-9002 fast-retransmit, a BBR-style congestion controller, and seamless connection migration (one live path at a time — Wi-Fi↔cellular without a re-handshake), all with no extra crypto layer. WASI and Embedded ride as framing legs. An optional mimicry feature (a TLS-over-TCP MimicTlsLegconnect_pinned_mimic / bind_mimic) makes a flow look like HTTPS to passive DPI + JA3/JA4 fingerprinting; it is anti-DPI obfuscation only and is detectable by active probing (see Status & limitations). Bandwidth aggregation across transports is deliberately not pursued. The UDP data plane is validated over a fault-injection rig but not yet soak-tested in the wild.
  • Multi-stream — strict-priority scheduler, WINDOW_UPDATE per-stream flow control, BBRv2-inspired pacing (Startup / Drain / ProbeBW / ProbeRTT / FastRecovery).
  • DoS-resistant handshake — stateless HMAC-SHA-256 cookie (hourly-rotated master) + adaptive blake3 proof-of-work (load-tiered difficulty 0–16).
  • Per-stream replay protection — RFC 4303 §3.4.3 sliding-window bitmap, default 1024 bits, checked after AEAD verify.
  • Observability — OpenTelemetry metrics + traces (opt-in telemetry-otel feature). Lock-free hot-path atomics (≤ 2.5 ns / call), OTLP/gRPC push to any backend (Datadog, Honeycomb, Grafana Cloud, self-hosted via OTel Collector). Pre-built Grafana dashboard + Prometheus alert rules in docs/observability/.
  • SLSA-3 build provenance — OIDC attestation on every release artifact.
  • Cross-platform — every CI target is a hard gate (Linux x4, macOS x2, iOS x2, Windows x2, wasm32-unknown-unknown, wasm32-wasip2, thumbv7em-none-eabihf); no allow_failure rows.

Quick start

Build / test / lint

cargo build   --manifest-path core/Cargo.toml
cargo test    --manifest-path core/Cargo.toml --lib
cargo clippy  --manifest-path core/Cargo.toml --lib -- -D warnings
cargo fmt     --manifest-path core/Cargo.toml --check

Loopback integration tests are #[ignore]-gated:

cargo test --manifest-path core/Cargo.toml --test tcp_integration -- --ignored

More commands (benches, fuzz, miri, cross-targets, embedded) are in CONTRIBUTING.md.

Minimal client / server

Server identity must be pinned — connect_with_transport requires a HybridVerifyingKey; there is no skip path (Security Invariant 1).

use phantom_protocol::api::{PhantomListener, PhantomSession, TcpSessionTransport};
use phantom_protocol::crypto::hybrid_sign::HybridVerifyingKey;
use tokio::net::TcpStream;

// ── Server ────────────────────────────────────────────────────────────────
let listener = PhantomListener::bind("127.0.0.1:0".to_string()).await?;
let server_addr = listener.local_addr();
let pinned_key  = listener.verifying_key_bytes();   // share out-of-band

tokio::spawn(async move {
    let outcome = listener.accept().await?;
    let session = outcome.session();
    let req = session.recv().await?;
    session.send(b"hello, post-quantum world".to_vec()).await?;
    Ok::<_, phantom_protocol::CoreError>(())
});

// ── Client (one-shot helper used by mobile / FFI consumers) ───────────────
let session = phantom_protocol::api::session::connect_pinned(
    "127.0.0.1".into(), 4242, pinned_key,
).await?;
session.send(b"ping".to_vec()).await?;
let reply = session.recv().await?;

// ── Or, explicit transport (TCP / WebSocket today; WASI / Embedded framing) ─
let stream    = TcpStream::connect(&server_addr).await?;
let transport = TcpSessionTransport::new(stream);
let key       = HybridVerifyingKey::from_bytes(&pinned_key)?;
let session   = PhantomSession::connect_with_transport(&server_addr, transport, key);

Runnable forms: core/examples/loopback_demo.rs, core/examples/embedded_demo.rs, core/examples/crypto_bench.rs.

Cryptography

Role Primitive Standard / source
KEM X25519 + ML-KEM-768 RFC 7748 + FIPS 203 (RustCrypto ml-kem)
Signatures Ed25519 + ML-DSA-65 FIPS 186-5 + FIPS 204 (RustCrypto ml-dsa)
AEAD (primary) AES-256-GCM ring, HW-accelerated (AES-NI / ARMv8 PMULL)
AEAD (fallback) ChaCha20-Poly1305 RFC 8439, auto-selected without AES intrinsics
KDF HKDF-SHA-256 RFC 5869
Hash / MAC SHA-256, HMAC-SHA-256, blake3 (keyed) FIPS 180-4 / FIPS 198-1 + non-FIPS

Phase 5.1 moved the PQ primitives off the C-bound pqcrypto-* crates to the RustCrypto FIPS-203 / FIPS-204 implementations. The crate compiles on wasm32-unknown-unknown and thumbv7em-none-eabihf without C bindings.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│  Public API   (core/src/api/)                                   │
│  PhantomSession · PhantomListener · TcpSessionTransport         │
├─────────────────────────────────────────────────────────────────┤
│  Transport    (core/src/transport/)                             │
│  Handshake{Client,Server} · Session · scheduler · pacer · paths │
│  api/{tcp,udp}_transport · legs/{websocket, wasi, embedded}     │
├─────────────────────────────────────────────────────────────────┤
│  Crypto       (core/src/crypto/)                                │
│  hybrid_kem · hybrid_sign · adaptive_crypto · kdf · pow · rng   │
├─────────────────────────────────────────────────────────────────┤
│  Security     (core/src/security/)                              │
│  ReplayWindow · ReplayProtection                                │
├─────────────────────────────────────────────────────────────────┤
│  Runtime      (core/src/runtime/)                               │
│  TokioRuntime (native) · WasmRuntime · (EmbeddedRuntime TODO)   │
└─────────────────────────────────────────────────────────────────┘

The formal architecture spec is docs/architecture/ARCHITECTURE.md; the unified wire protocol (incl. 0-RTT) is docs/protocol/PROTOCOL.md. Per-subsystem security invariants are catalogued in docs/security/threat-model.md.

Transport features

  • Single unified wire protocol. One PacketHeader (15 bytes on the wire, fully header-protected — the variable header fields and the leading version byte are HP-masked; the AEAD AAD image is 47 bytes) wrapped in a bare PhantomPacket (header + payload + TLV-headroom extensions) — no VersionedPacket enum, no per-session wire-version negotiation. epoch, REKEY, PATH_VALIDATION, COALESCED, WINDOW_UPDATE flags live in the one header; the recv path deserializes PhantomPacket directly and drops any frame whose header.version differs. Handshake messages are bare borsh structs (no envelopes): one ClientHello (with the optional 0-RTT early_data blob folded in), one ServerHello, one HelloRetryRequest, one signed HandshakeTranscript leading with protocol_variant. WIRE_VERSION is 6 (PROTOCOL_VERSION is 3); both pinned bytes are tamper-check anchors and a hook for a future deliberate bump.
  • Path validation (wired into the live UDP data plane). PathRegistry + constant-time challenge/response; path 0 pre-validated, secondary paths transition Unvalidated → Validating → Validated. It backs the PhantomUDP data plane end-to-end — the PATH-001 send-gate + recv-relax, seamless connection migration (one live path at a time), and passive-NAT-rebind recovery. Only bandwidth aggregation / simultaneous multipath is unbuilt (rejected for this workload — see Status & limitations).

Performance

Reference numbers on Apple M1 Pro (8P + 2E, 16 GiB), macOS 26.0, rustc 1.93.0, ring with ARMv8 AES-PMULL (snapshot 2026-05-17, criterion --quick, default target-cpu):

Path Number Notes
Hybrid PQ handshake (pinned) 1.06 ms / ~945 conn/s/core full production path; ~7,500 cold handshakes/s aggregate on 8P cores
AEAD encrypt, 64 KiB 4.67 GiB/s/core (13.1 µs) encrypt_packet with header-AAD + replay window
AEAD decrypt, 16 KiB 4.68 GiB/s/core same path
1 MiB round-trip 391.5 µs5.0 GiB/s encrypt + decrypt
Raw AES-256-GCM (ring) 5,514 MiB/s at 64 KiB bare cipher, no framing
ChaCha20-Poly1305 (software) 1,555 MiB/s at 1 MiB ~3.5× slower than AES on this part
ClientHello parse + cookie + reputation 4.60 µs / ~217K/s/core DoS gate hot path
kem_encapsulate 80.7 µs hybrid X25519 + ML-KEM-768
hybrid_sign / hybrid_verify 310.0 µs / 131.6 µs Ed25519 + ML-DSA-65

RUSTFLAGS="-C target-cpu=native" typically adds +5–10%; PGO via cargo-pgo adds another +5–10% on stable workloads. The release profile (opt-level=3, lto="fat", codegen-units=1, panic="abort") is set at the workspace root. Linux x86_64 with AES-NI lands in similar ballparks. Full methodology and production tuning (bbr, fq, LimitNOFILE, allocator swap, CPU pinning) in BENCHMARKS.md and docs/operations/perf-tuning.md.

Deploying

phantom-server (reference binary)

Production embedder. Auto-loads-or-creates a persistent HybridSigningKey, pushes OTLP telemetry to an OTel Collector / SaaS backend, handles SIGTERM / SIGINT with a 10s drain.

Flag Env Default
--bind PHANTOM_BIND 0.0.0.0:4242
--otlp-endpoint OTEL_EXPORTER_OTLP_ENDPOINT http://localhost:4317
--otel-service-name OTEL_SERVICE_NAME phantom-server
--otel-trace-sample-ratio OTEL_TRACES_SAMPLER_ARG 0.01
--signing-key-file PHANTOM_SIGNING_KEY_FILE /etc/phantom-server/signing.key (0600, auto-created)
--log-json PHANTOM_LOG_JSON false
--log-filter RUST_LOG info,phantom_protocol=debug
cargo run --manifest-path server/Cargo.toml -- \
    --bind 0.0.0.0:4242 \
    --otlp-endpoint http://otel-collector:4317

Docker / docker-compose

Multi-stage Dockerfile (rust:1-slim-bookwormdebian:bookworm-slim), non-root phantom UID 65532, EXPOSE 4242 + 9090, signing-key volume at /etc/phantom-server. docker-compose.yml is ready to run with a named volume and TCP healthcheck.

docker build -t phantom-server:0.2.2 .
docker compose up -d

Kubernetes / Helm

Production-shape chart at docs/operations/helm/phantom-protocol/. appVersion: 0.2.2, ClusterIP service on 4242, 3 replicas, tcpSocket liveness / readiness. Raw manifests + walkthrough in docs/operations/kubernetes.md.

systemd

Hardened unit text in docs/operations/systemd.md (NoNewPrivileges, ProtectSystem=strict, MemoryDenyWriteExecute, SystemCallFilter, 30s TimeoutStopSec) plus a multi-instance template using SO_REUSEPORT.

Observability

OpenTelemetry metrics + traces over OTLP/gRPC (Phase 8 — replaces the Phase 4.5 hand-rolled Prometheus endpoint). The reference server pushes to OTEL_EXPORTER_OTLP_ENDPOINT; backends supported include OTel Collector (→ Prometheus / Tempo / Loki), Datadog, Honeycomb, Grafana Cloud, AWS CloudWatch — anything OTLP-compatible. Pre-built Grafana dashboard at docs/observability/grafana/phantom-otel-dashboard.json and Prometheus alert rules at docs/observability/prometheus/alerts.yml. End-to-end docker-compose demo in examples/observability-demo/. Full setup recipes in docs/observability/otlp-setup.md.

CLI

phantom-cli (sibling crate, edition 2024):

cargo run --manifest-path cli/Cargo.toml -- keygen --out ./server.key
cargo run --manifest-path cli/Cargo.toml -- pubkey --in  ./server.key
cargo run --manifest-path cli/Cargo.toml -- ping --host 127.0.0.1 --port 4242 \
    --pinned-key-hex <hex-from-keygen> --msg hello
cargo run --manifest-path cli/Cargo.toml -- version

Platforms & language bindings

Cross-compile matrix (.github/workflows/cross.yml)

Target Status
x86_64-unknown-linux-gnu / aarch64-unknown-linux-gnu / aarch64-unknown-linux-musl hard gate
x86_64-apple-darwin / aarch64-apple-darwin hard gate
aarch64-apple-ios (device) / aarch64-apple-ios-sim hard gate
x86_64-pc-windows-msvc / aarch64-pc-windows-msvc hard gate
wasm32-unknown-unknown hard gate (Phase 3.3 / 3.5)
thumbv7em-none-eabihf hard gate (Phase 3.6; --no-default-features --features embedded,no-std)
wasm32-wasip2 hard gate (compile + host round-trip; WASI is client-side framing-only — see docs/operations/wasi.md)

Language bindings (tests/bindings/)

Binding Maturity Notes
Swift Production-shape Auto-gen via UniFFI 0.29; iOS XCFramework recipe in docs/operations/mobile.md
Kotlin Production-shape Auto-gen; Android NDK + Gradle jniLibs recipe in mobile.md
Python UniFFI surface auto-gen Demo harness tests/run_test.py is stale and references a previous API
C Experimental Hand-curated header — UniFFI 0.29 has no C generator. Covers connect_pinned but not HybridSigningKey or PhantomConfig. README recommends Swift / Kotlin / Python instead
WASM (browser) Demo shipped examples/wasm-demo/ pairs with docs/operations/wasm.md; uses WebSocketLeg + WasmRuntime

Regen: tests/bindings/{generate_swift,generate_kotlin,generate_c}.sh.

Embedded (embedded feature, default off)

On bare-metal thumbv7em-none-eabihf Phantom Protocol ships the framing transport onlyEmbeddedLeg and its length-prefix codec. The PQ handshake, PhantomSession, the crypto primitives, and TokioRuntime are std-gated and not built there; a bare-metal embedder brings its own crypto/handshake driver and runs it over the leg. PQ-on-bare-metal is descoped for 1.0 (see Status & limitations).

EmbeddedLeg<R, W, const N: usize> wraps any embedded-io-async = 0.6 byte stream (UART, USB-CDC, …) with 4-byte BE length-prefix framing — the same wire shape as TcpSessionTransport. Pure-Rust, no_std + alloc, target-arch-agnostic (builds on host x86_64 for unit tests and on bare-metal thumbv7em-none-eabihf). Per-(R, W) SessionTransport impl via the impl_embedded_session_transport! macro. RngProvider trait injects a hardware RNG when getrandom isn't available. core/examples/embedded_demo.rs runs the full session over a mock byte stream on a host (std), demonstrating the leg — not a bare-metal handshake.

Security

Full threat model, mitigations, and disclosure policy are in SECURITY.md and docs/security/threat-model.md. Headline points:

  • Mandatory server identity pinningconnect_with_transport requires a HybridVerifyingKey; no skip path.
  • Forward secrecy — ephemeral hybrid KEM per handshake + HKDF-based mid-session rekey (epoch saturates at u8::MAX, never wraps).
  • Replay rejection happens after AEAD verify — RFC 4303 §3.4.3 sliding-window bitmap, per-stream.
  • Downgrade resistance — the pinned protocol version and protocol_variant are signed under the handshake transcript; stripped-ENCRYPTED post-handshake packets are dropped.
  • 0-RTT anti-replaySessionCache::try_resume consumes the resumption ticket on first lookup; oversized / expired / AEAD-failing early-data is best-effort and never fatal to the handshake.
  • AEAD nonce-exhaustion guardCryptoError::NonceExhausted at AEAD_MAX_INVOCATIONS = 2^48.
  • ZeroizeOnDrop on all key-bearing structs; #![deny(unsafe_code)] crate-wide with three audited opt-ins (transport/udp_transport.rs libc setsockopt pacing, transport/legs/websocket.rs wasm-bindgen glue, transport/legs/wasi.rs WIT-bindgen Send/Sync).
  • Cancel-safety audit: zero bugs found across all tokio::select! sites.
  • Documented production panic sites with PANIC-SAFETY: invariants — see docs/security/panic-sites.md.

FIPS 140-3 / Common Criteria — exploratory only, NOT validated

No FIPS validation and no Common Criteria evaluation exist, and none is in progress. The files under docs/compliance/ are self-authored readiness/gap analyses, not certifications — do not rely on them for any compliance claim.

  • FIPS 140-3: the crypto uses several FIPS-approved primitives (ML-KEM-768, ML-DSA-65, Ed25519, SHA-256, HMAC/HKDF-SHA-256), and an optional fips Cargo feature swaps the remaining non-approved primitives toward an aws-lc-rs substrate. This is not a validated cryptographic module (no CMVP). Gap analysis: docs/compliance/fips-readiness.md; CAVP-style known-answer vectors in core/tests/cavp.rs.
  • Common Criteria: an internal SFR gap-mapping exercise against NIAP PP-Module VPN Client exists for design reference only (docs/compliance/cc-pp-mapping.md). No lab evaluation is planned.

Disclosure

Report privately, not via public issues. Embargo SLA 90 days; ack within 5 business days, triage within 14. Contact in SECURITY.md (the email there is a placeholder pending crate publication).

Supply chain

cargo deny (permissive-license allowlist, yanked = "deny", unknown-registry = "deny") and cargo audit run in CI. Release artifacts carry SLSA-3 OIDC build-provenance attestations via actions/attest-build-provenance@v2. Verify with gh attestation verify --owner <org> <artifact> or cosign verify-blob-attestation.

Status & limitations

Maturity: early. Not production-ready. This is a single implementation with no external security audit. The cryptographic handshake + identity layer and the UDP data plane (SACK loss recovery, congestion control, connection migration) are implemented and tested — the data plane against a deterministic fault-injection transport (loss / reorder) and the udp_integration loopback suite. The gating limitation is the absence of an independent security audit and the pre-1.0 wire churn — not an unfinished data plane. Do not protect anything high-risk with this until it has been independently audited and soak-tested on real networks.

  • Pre-1.0 (0.2.2). Wire format may break between minors; SemVer applies once 1.0 ships. The current wire protocol is a single pinned version — the former V1/V2/V3 axes were collapsed pre-1.0 (no users, no negotiation, no fallback), so there are no cross-version migration guides.
  • Native UDP transport (PhantomUDP): handshake + demux + reliability shipped. PhantomSession runs an authenticated session over TCP, WebSocket, and raw UDP (connection-ID demux, server accept, fragmented handshake). The UDP data plane has SACK-based loss recovery (RFC-9002-style fast-retransmit) + an RFC-6298 RTO
    • a BBR-style congestion controller + mid-session rekey, exercised over a deterministic fault-injection transport (loss / reorder — test_harness/fault_transport.rs) and the udp_integration suite. Seamless connection migration (one live path at a time, Wi-Fi↔cellular without re-handshake) shipped too. The earlier experimental KCP / FakeTLS legs and the unused TransportLeg multipath trait were removed (never wired into the data plane). Bandwidth aggregation across transports is not planned — analysis showed it regresses for this workload and harms unobservability. What remains: real-world soak + an external audit (not lab-rig coverage).
  • TLS-mimicry transport (mimicry feature, off by default). A MimicTlsLeg makes a Phantom flow look like ordinary HTTPS (a synthetic TLS 1.3 handshake, then the session inside ApplicationData records) to defeat DPI that blocks unknown/high-entropy traffic. The outer TLS is anti-DPI obfuscation only — the handshake is theater (no real ECDHE/cert) and holds no keys; the inner Phantom PQ session is the sole auth/conf. It defeats parsers, not provers: a determined active-probing censor that completes a real TLS handshake detects it in one round trip, and against such an adversary it is net-negative. Use only where the threat is passive/commercial DPI, not active probing. Honest residuals
  • Mobile connection migration (Wi-Fi ↔ LTE): reconnect with 0-RTT, not migrate(). PhantomSession.migrate() is on the FFI surface, but it is a no-op over the TCP transport the bindings use (real single-socket migration is UDP-only and not yet FFI-exposed). On a network change, reconnect — folding the first request in via connect_pinned_with_resumption to minimise cost. The examples/mobile/ sample apps implement exactly this; see docs/operations/mobile.md.
  • Work deferred past 0.2.0 — hermetic/reproducible builds, the no-std PQ handshake, WASI server-side sessions, and ECN congestion feedback — is consolidated with rationale in docs/DEFERRED_WORK.md.
  • Loss recovery: SACK + fast-retransmit, validated over a fault rig (not yet in the wild). The UDP data plane has RFC-9002-style SACK + dup-ACK fast-retransmit, an RFC-6298 RTO, a BBR-style congestion window, and mid-session rekey. It is exercised by udp_integration over test_harness/fault_transport.rs (injected loss + reorder), but has not been hardened against real-world adversarial network conditions or externally reviewed — treat the data plane as functional-but-not-battle-tested.
  • Negative-security suite: 58 always-on tests in core/tests/security_invariants.rs, pinning every documented invariant. Plus the proptest, fuzz, wire-vector, runtime-integration, and CAVP suites, 400+ library unit tests, and #[ignore]-gated loopback integration suites (TCP, UDP — including injected loss/reorder via the fault transport — WASI, TLS-mimicry). 0 workspace warnings, 0 clippy warnings. Note: broad test coverage + a fault-injection rig is not a substitute for an external security audit or a real-world soak.
  • Broad feature coverage across the planned phases, but not production-ready. The handshake / identity / data-plane / observability / cross-target work is in place and tested; what remains open is an external security audit, CMVP/CC validation, formal verification (ProVerif / Tamarin), and a real-world soak — none done.
  • PhantomListener::bind() generates a fresh signing key per process — identities don't survive restart. Pin-stable production deployments must use bind_with_signing_key() with a key loaded from disk (phantom-cli keygen writes 0600 seed files).
  • The library ships no HTTP server. The library exposes OTel instruments; embedders configure the exporter. server/src/telemetry.rs is the reference OTLP/gRPC wiring.
  • MSRV: Rust 1.93 (raised from 1.75 — the PQ crates pull pkcs8 0.11 → edition2024 → Rust ≥1.85; the CI gate is 1.93). cli/ uses edition 2024.
  • 7 fuzz harnesses, run in CI (.github/workflows/fuzz.yml: 60 s per target per PR, 600 s nightly). Fuzzing needs nightly; only fuzz_embedded_framing's body also compiles on stable.
  • Embedded is framing-only on bare-metal. The thumbv7em-none-eabihf build (--no-default-features --features embedded,no-std) ships EmbeddedLeg + its length-prefix framing; the PQ crypto, handshake, and PhantomSession are std-gated out. PQ-on-bare-metal is descoped for 1.0 — the RustCrypto primitives need alloc plus entropy/heap the embedder supplies, and a real bare-metal handshake (no-std crypto, an Embassy/RTIC runtime, a QEMU-hosted handshake test) is a separate sub-project. Bare-metal embedders run their own crypto over the leg. The hard thumbv7em CI gate is cargo check --lib — it proves the framing compiles, not that a session runs.

Documentation

Contributing

See CONTRIBUTING.md. PRs must pass cargo fmt --check, cargo clippy --lib -- -D warnings, cargo test --lib, and cargo deny check. The cli-check CI job requires that core API edits keep cli/ building.

Acknowledgements

Developed with AI assistance from Anthropic's Fable 5 via Claude Code. All architectural decisions, security invariants, threat model, and FIPS / CC compliance artifacts are authored, reviewed, tested, and maintained by the human author.

License

Apache License 2.0. See LICENSE.

About

Post-quantum-secure L4/L6 transport SDK in Rust. Hybrid X25519+ML-KEM-768 / Ed25519+ML-DSA-65 over reliable-UDP (PhantomUDP) / TCP / WebSocket, with connection migration, 0-RTT resumption, optional HTTPS mimicry, and FFI to Swift/Kotlin/Python/C.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Contributors