Methodology Reference: NCT / NACT / NSCT¤
Overview¤
PANTHER's Ivy formal verification integrates three complementary compositional testing methodologies:
| Methodology | Full Name | Perspective | Environment |
|---|---|---|---|
| NCT | Network-Centric Compositional Testing | Specification compliance | Real network |
| NACT | Network-Attack Compositional Testing | Attacker behavior | Real network |
| NSCT | Network-Simulator Centric Compositional Testing | Scale & topology | Simulated network |
All three share the same foundational Ivy formal specification language and the 14-layer template architecture, but differ in their testing perspective, entity roles, and execution environment.
1. NCT -- Network-Centric Compositional Testing¤
1.1 Core Concept¤
NCT tests protocol implementations by having a formal specification play one role in the protocol (client, server, or man-in-the-middle) against an Implementation Under Test (IUT). The formal specification: - Generates test traffic using Z3/SMT symbolic execution - Monitors received packets against specification assertions - Checks that the IUT's behavior complies with the protocol specification
This is "compositional" because the specification is decomposed into modular layers that can be tested independently or composed.
1.2 Role Inversion¤
A key concept in NCT: the Ivy tester's role is the opposite of what it tests. - Testing a QUIC server -> Ivy acts as a formal client (quic_server_test_ files) - Testing a QUIC client -> Ivy acts as a formal server (quic_client_test_ files) - MIM testing -> Ivy acts as a man-in-the-middle (quic_mim_test_* files)
The oppose_role() function in panther_ivy handles this mapping.
1.3 Specification Structure¤
Protocol specifications use a layered architecture with monitors (before/after clauses) attached to protocol events:
before clauses (preconditions/guards): - Define what conditions must hold before an event can occur - Act as guards: if the precondition fails, the event is blocked - Example: before sending a packet, the connection must be in the correct state
after clauses (state updates/checks): - Define state updates and checks after an event occurs - Record history information by updating shared variables - Check specification compliance of received data - Example: after receiving a packet, verify it has the correct format and update connection state
_finalize() (end-state verification): - Called when the test completes - Performs heuristic checks on the overall test outcome - Example: verify that some data was actually received, no errors occurred
1.4 Test Specification Example (from QUIC)¤
Here is the structure of a QUIC server test (quic_server_test.ivy):
#lang ivy1.7
include order
include quic_infer
include file
include ivy_quic_shim_client # Shim: Ivy acts as client
include quic_locale
include ivy_quic_client_behavior # Entity behavior for client role
include ivy_quic_client_standard_tp # Initial transport parameters
include quic_time
after init {
# Initialize network sockets, TLS, transport parameters
sock := net.open(endpoint_id.client, client.ep);
client.set_tls_id(0);
server.set_tls_id(1);
var extns := tls_extensions.empty;
extns := extns.append(make_transport_parameters);
call tls_api.upper.create(0, false, extns); # false = not a server
}
# Export actions to be generated by the test mirror
export frame.ack.handle
export frame.stream.handle
export frame.crypto.handle
export frame.path_response.handle
export packet_event
export client_send_event
export tls_recv_event
# Final verification
export action _finalize = {
require is_no_error;
require conn_total_data(the_cid) > 0; # Some data was received
}
Test variants (e.g., quic_server_test_stream.ivy) include the base test and add weight attributes:
#lang ivy1.7
include quic_server_test
attribute frame.crypto.handle.weight = "5"
attribute frame.path_response.handle.weight = "5"
1.5 NCT Workflow¤
- Select target protocol and RFC -- identify which protocol to test and which RFC defines it
- Decompose into 14 formal layers -- map RFC sections to the template layers
- Write type definitions -- {prot}_types.ivy (foundation layer)
- Build core stack -- frames -> packets -> protection -> connection
- Define entity roles -- client, server, MIM instances
- Write behavioral constraints -- before/after monitors encoding RFC requirements
- Create test specifications -- role-specific tests with _finalize
- Verify -- ivy_check for formal properties
- Compile -- ivyc target=test to produce test binaries
- Execute against IUT -- run compiled test against implementation
1.6 Directory Structure¤
protocol-testing/{prot}/
├── {prot}_stack/ # Core protocol model (layers 1-9)
├── {prot}_entities/ # Entity definitions and behavior (layers 10-12)
├── {prot}_shims/ # Implementation bridge (layer 12)
├── {prot}_utils/ # Serialization, utilities (layers 13-14)
├── {prot}_tests/
│ ├── server_tests/ # Tests targeting server IUTs (Ivy acts as client)
│ ├── client_tests/ # Tests targeting client IUTs (Ivy acts as server)
│ └── mim_tests/ # Man-in-the-middle tests
└── {prot}_attacks_stack/ # Optional APT integration
1.7 Serena Tools for NCT¤
| Step | Serena Tool | Purpose |
|---|---|---|
| Navigate specs | find_symbol, get_symbols_overview | Understand existing spec structure |
| Read spec code | read_file | Read specific sections of .ivy files |
| Trace deps | find_referencing_symbols | Find what references a symbol |
| Search patterns | search_for_pattern | Find patterns across specs |
| Verify | ivy_check | Check formal properties |
| Compile | ivy_compile | Build test executables |
| Inspect model | ivy_model_info | View model types, relations, actions |
| Create specs | create_text_file | Write new .ivy files |
| Edit specs | replace_symbol_body | Modify existing symbols |
2. NACT -- Network-Attack Compositional Testing¤
2.1 Core Concept¤
NACT extends NCT to model and test from an attacker's perspective. It uses the APT (Advanced Persistent Threat) lifecycle model to systematically test security properties of protocol implementations. Attack specifications use the same Ivy formal language and before/after monitor pattern as NCT.
2.2 APT 6-Stage Lifecycle¤
The APT lifecycle is organized into 3 phases with 6 stages plus a cross-cutting concern:
Phase 1: Infiltration
1. Reconnaissance -- Gather information about the target (WHOIS, DNS queries, port scanning, service enumeration, OS fingerprinting, banner grabbing). Defined in attack_reconnaissance.ivy.
- Actions: launch_whois_lookup(), launch_dns_query(), endpoint_scanning(src, dst)
- Types: passive (OSINT, social engineering) and active (port scanning, network scanning)
-
Infiltration -- Initial access to the target network. Defined in
attack_infiltration.ivy. -
C2 Communication -- Establish command & control channels. Defined in
attack_c2_communication.ivy.
Phase 2: Expansion
4. Privilege Escalation -- Gain higher access levels. Defined in attack_privilege_escalation.ivy.
- Persistence -- Maintain access to the compromised system. Defined in
attack_maintain_persistence.ivy.
Phase 3: Extraction
6. Exfiltration -- Extract data from the target. Defined in attack_exflitration.ivy.
Cross-cutting: White Noise -- Distraction attacks to cover the primary attack. Defined in attack_white_noise.ivy.
The lifecycle is composed in attack_life_cycle.ivy:
#ivy lang1.7
include attack_white_noise
# Infiltration
include attack_reconnaissance
include attack_infiltration
include attack_c2_communication
# Expansion
include attack_privilege_escalation
include attack_maintain_persistence
# Extraction
include attack_exfiltration
2.3 APT Directory Structure¤
protocol-testing/apt/
├── apt_entities/ # Attack entity definitions (attacker, bot, C2, target, MIM)
├── apt_entities_behavior/ # Attack entity behavioral constraints
├── apt_lifecycle/ # 6-stage lifecycle definitions
│ ├── attack_life_cycle.ivy # Master include file
│ ├── attack_reconnaissance.ivy
│ ├── attack_infiltration.ivy
│ ├── attack_c2_communication.ivy
│ ├── attack_privilege_escalation.ivy
│ ├── attack_maintain_persistence.ivy
│ ├── attack_exflitration.ivy
│ ├── attack_white_noise.ivy
│ ├── apt_attack_connection.ivy
│ ├── apt_datagram.ivy
│ ├── apt_packet.ivy
│ └── (protocol-specific bindings:)
│ ├── quic_apt_lifecycle/ # QUIC-specific attack bindings
│ ├── minip_apt_lifecycle/ # MiniP-specific attack bindings
│ ├── udp_apt_lifecycle/ # UDP-specific attack bindings
│ └── stream_data_apt_lifecycle/
├── apt_network/ # Attack network infrastructure models
├── apt_protocols/ # Protocol-specific APT integration
│ └── {prot}/ # Per-protocol attack model overlays
├── apt_shims/ # Attack implementation bridges
├── apt_stack/ # Attack protocol stack layers
├── apt_tests/ # Attack test specifications
│ ├── server_attacks/ # Tests attacking server IUTs
│ ├── client_attacks/ # Tests attacking client IUTs
│ └── mim_attacks/ # Man-in-the-middle attack tests
├── apt_utils/ # Attack utilities
└── test/ # Test infrastructure
2.4 Protocol-Specific Bindings¤
Each supported protocol has attack bindings that connect the generic APT lifecycle to protocol-specific actions:
- QUIC: quic_apt_lifecycle/ -- maps reconnaissance to QUIC endpoint scanning, infiltration to connection manipulation, etc.
- MiniP: minip_apt_lifecycle/ -- simplified protocol attack bindings
- UDP: udp_apt_lifecycle/ -- basic datagram-level attack bindings
- Stream Data: stream_data_apt_lifecycle/ -- stream-oriented attack bindings
2.5 NACT Workflow¤
- Define threat model -- Identify which APT stages apply to the target protocol
- Design attack entities -- Define attacker roles and capabilities in apt_entities/
- Write attacker behavioral constraints -- FSM and before/after monitors for attack actions
- Create protocol-specific bindings -- Map generic attack stages to protocol actions
- Write attack test specifications -- Create test files in apt_tests/
- Verify attack specs -- ivy_check to ensure attack model consistency
- Compile attack tests -- ivyc to produce attack test executables
- Execute against IUT -- Run attack tests against protocol implementations
- Analyze security properties -- Check whether IUT correctly handles attack scenarios
2.6 Serena Tools for NACT¤
Same tools as NCT (section 1.7), with additional focus on:
- Navigating apt/ directory structure
- Understanding attack entity formal models
- Tracing protocol-specific bindings
3. NSCT -- Network-Simulator Centric Compositional Testing¤
3.1 Core Concept¤
NSCT uses the Shadow Network Simulator to run protocol tests in a deterministic, simulated network environment. This enables: - Scale testing: Run many nodes simultaneously in a controlled environment - Topology testing: Define complex network topologies (meshes, hierarchies, partitions) - Deterministic replay: Same simulation produces same results (useful for debugging) - Network condition modeling: Simulate latency, loss, bandwidth constraints
3.2 Shadow NS Integration¤
PANTHER integrates Shadow NS as an execution environment alternative to Docker Compose: - Docker Compose (NCT/NACT): Real network stack, isolated containers - Shadow NS (NSCT): Simulated network stack, deterministic execution
Configuration uses PANTHER experiment configs with type: shadow_ns in the network_environment section:
tests:
- name: "NSCT Test"
network_environment:
type: shadow_ns
topology:
# Shadow NS topology configuration
services:
server:
implementation:
name: picoquic
type: iut
protocol:
name: quic
version: rfc9000
role: server
3.3 When to Use NSCT vs NCT¤
| Criterion | NCT (Real Network) | NSCT (Simulated) |
|---|---|---|
| Fidelity | High (real OS stack) | Medium (simulated stack) |
| Scale | Limited (container resources) | High (many simulated nodes) |
| Determinism | Non-deterministic | Deterministic |
| Topology control | Basic (Docker networks) | Full (arbitrary topologies) |
| Network conditions | Limited manipulation | Full control |
| Debugging | Harder (non-deterministic) | Easier (deterministic replay) |
| Performance testing | Realistic | Simulated |
3.4 NSCT Workflow¤
- Define network topology -- Specify nodes, links, latencies, bandwidths
- Configure simulation parameters -- Duration, seed, logging level
- Set up protocol implementations -- Map IUTs to simulated nodes
- Define formal specifications -- Same Ivy specs as NCT (reuse)
- Run simulation-based verification -- Execute via PANTHER with shadow_ns environment
- Analyze results -- Examine simulation logs and verification output
3.5 Complementarity¤
The three methodologies are designed to be complementary: - NCT verifies specification compliance in realistic conditions - NACT verifies security properties under adversarial conditions - NSCT verifies behavior at scale and under varied network conditions
A comprehensive testing campaign would use all three: 1. NCT to verify basic protocol compliance 2. NACT to test resilience against attacks 3. NSCT to verify behavior at scale and under adverse network conditions
4. The 14-Layer Template (Shared Foundation)¤
All three methodologies share the same 14-layer formal model template. This template provides a structural pattern for decomposing any network protocol into modular Ivy specifications.
4.1 Core Protocol Stack (Layers 1-9, Always Required)¤
| # | Layer | File Pattern | Purpose |
|---|---|---|---|
| 1 | Type Definitions | {prot}_types.ivy |
Identifiers, bit vectors, enumerations |
| 2 | Application | {prot}_application.ivy |
Data transfer semantics |
| 3 | Security/Handshake | {prot}_security.ivy |
Key establishment, handshake |
| 4 | Frame/Message | {prot}_frame.ivy |
Protocol data unit definitions |
| 5 | Packet | {prot}_packet.ivy |
Wire-level packet structure |
| 6 | Protection | {prot}_protection.ivy |
Encryption/decryption |
| 7 | Connection/State | {prot}_connection.ivy |
Session lifecycle |
| 8 | Transport Parameters | {prot}_transport_parameters.ivy |
Negotiable parameters |
| 9 | Error Handling | {prot}_error_code.ivy |
Error taxonomy |
4.2 Entity Model (Layers 10-12, Always Required)¤
| # | Layer | File Pattern | Purpose |
|---|---|---|---|
| 10 | Entity Definitions | ivy_{prot}_{role}.ivy |
Network participant instances |
| 11 | Entity Behavior | ivy_{prot}_{role}_behavior.ivy |
FSM and constraints |
| 12 | Shims | {prot}_shim.ivy |
Implementation bridge |
4.3 Infrastructure (Layers 13-14, Mostly Reusable)¤
| # | Layer | File Pattern | Purpose |
|---|---|---|---|
| 13 | Serialization/Deserialization | {prot}_ser.ivy, {prot}_deser.ivy |
Wire format encoding |
| 14 | Utilities | byte_stream.ivy, file.ivy, time.ivy, random_value.ivy, locale.ivy |
Common utilities |
4.4 Optional Layers¤
- Security Sub-Protocol (
tls_stack/ordtls_stack/) - FSM Modules (
{prot}_fsm/) - Recovery & Congestion (
{prot}_recovery/or{prot}_congestion/) - Extensions (
{prot}_extensions/) - Attacks Stack (
{prot}_attacks_stack/) - Stream/Flow Management (
{prot}_stream.ivy)
4.5 Genuinely Reusable Components¤
Only these components are identical across protocols:
- byte_stream.ivy -- byte stream manipulation
- file.ivy -- file I/O
- random_value.ivy -- random value generation
- The shim pattern (not implementation) -- same bridge architecture
- The _finalize() pattern -- same end-state verification approach
- The before/after monitor pattern -- same specification approach
4.6 Decision Matrix¤
| Protocol Property | Template Impact |
|---|---|
| Connection-oriented? | TCP layer, simplified packet structure |
| Built-in reliability? | Add recovery/congestion modules |
| Multiplexed streams? | Add stream management + per-stream FSM |
| Integrated security? | Add TLS/DTLS stack + protection layer |
| Peer-to-peer? | Symmetric entities (Speaker/Peer) |
| Pub/Sub pattern? | Add broker entity + topic/subscription |
| Extension mechanism? | Add extensions module |
| Stateless? | Simplify connection/state management |
| Tunneling? | Add encapsulation + SA management |
| Real-time? | Add timing constraints + FEC recovery |
5. Serena Tool Reference for All Methodologies¤
5.1 Ivy-Specific Tools (from panther-serena)¤
ivy_check -- Formal verification
- Parameters: relative_path (str), isolate (str|None), max_answer_chars (int)
- Runs: ivy_check [isolate=X] path.ivy
- Checks: isolate assumptions, invariants, safety properties
- Returns: JSON {stdout, stderr, return_code}
ivy_compile -- Test compilation
- Parameters: relative_path (str), target (str, default "test"), isolate (str|None), max_answer_chars (int)
- Runs: ivyc target=X [isolate=Y] path.ivy
- Produces: compiled test executable
- Returns: JSON {stdout, stderr, return_code}
ivy_model_info -- Model introspection
- Parameters: relative_path (str), isolate (str|None), max_answer_chars (int)
- Runs: ivy_show [isolate=X] path.ivy
- Shows: types, relations, actions, invariants, isolates
- Returns: JSON {stdout, stderr, return_code}
5.2 Standard Serena Tools (for code navigation)¤
| Tool | Purpose | When to Use |
|---|---|---|
| find_symbol | Find symbol by name path | Navigate to specific functions/modules |
| get_symbols_overview | List top-level symbols in file | Understand file structure |
| find_referencing_symbols | Find what references a symbol | Trace dependencies |
| search_for_pattern | Regex search across files | Find patterns in specs |
| read_file | Read file contents | View specific .ivy files |
| create_text_file | Create new file | Write new specs |
| replace_symbol_body | Replace symbol implementation | Edit existing specs |
| replace_content | Replace content by regex | Fine-grained edits |
| list_dir | List directory contents | Explore directory structure |
| find_file | Find file by name | Locate spec files |
6. File Naming Conventions¤
| Pattern | Example (QUIC) | Description |
|---|---|---|
{prot}_types.ivy |
quic_types.ivy |
Type definitions |
{prot}_frame.ivy |
quic_frame.ivy |
Frame/message definitions |
{prot}_packet.ivy |
quic_packet.ivy |
Packet structure |
ivy_{prot}_{role}.ivy |
ivy_quic_client.ivy |
Entity definition |
ivy_{prot}_{role}_behavior.ivy |
ivy_quic_client_behavior.ivy |
Entity behavior |
{prot}_shim.ivy |
quic_shim.ivy |
Implementation bridge |
{prot}_server_test.ivy |
quic_server_test.ivy |
Base server test |
{prot}server_test.ivy |
quic_server_test_stream.ivy |
Test variant |
{prot}_ser.ivy / {prot}_deser.ivy |
quic_ser.ivy / quic_deser.ivy |
Serialization |
attack_{stage}.ivy |
attack_reconnaissance.ivy |
APT lifecycle stage |
{prot}_apt_lifecycle/ |
quic_apt_lifecycle/ |
Protocol-specific APT bindings |