Craton Shield
vs-iec61850-monitor
IEC 61850 MMS / GOOSE / SV anomaly detection for Craton Shield (IEC 62443).
Overview
Monitors IEC 61850 traffic (MMS, GOOSE, and Sampled Values protocols) for behavioural anomalies in substation automation systems. Designed for IEDs, gateways, and merging units.
MSRV: 1.82 | Environment: #![no_std], zero heap allocation
Security model
This crate does NOT implement IEC 62351-6 GOOSE/SV authentication. There is no HMAC verification, no signing, and no cryptographic trust root. Frames are accepted on the wire as-is; the monitor only inspects their plaintext fields.
Detection is heuristic, based on:
src_macof the publishing Ethernet frame,stNum/sqNumcounters and baseline-no-downgrade rules,- timing windows (retransmission decay,
t-field monotonicity), - per-publisher bindings learned from configuration or observation.
An attacker who can replicate a legitimate publisher's src_mac and
increment the stNum / sqNum counters correctly cannot be detected
by this crate. Layer-2 MAC spoofing on a shared substation LAN is
trivial for any attacker with bus access. Treat alerts as forensic /
anomaly signals, not as authenticated rejection of a cryptographically
untrusted peer.
For production-grade authentication, consult IEC 62351-6:2020 (cyber security for IEC 61850 GOOSE and Sampled Values) and provide a HMAC / signature-verifying layer below or alongside this monitor.
Features
MMS (Manufacturing Message Specification)
- Service-type allowlist -- bitmask filter for MMS confirmed service types
- Write protection -- block Write, Define/Delete operations
- Rate limiting -- per-invoke-ID token buckets
- Control-block reservation tracking -- observe
SelectControlandCancelControloperations and remember which client owns each GoCB / SvCB. Subsequent GOOSE / SV traffic addressing a reserved control block from a different publisher MAC is flagged asAlertCode::CbHijack(heuristic hijack indicator; not authenticated rejection).
GOOSE (Generic Object Oriented Substation Event)
- Publisher allowlist -- restrict allowed (src_mac, GoCBRef) pairs
(note:
src_macis trivially forgeable; see Security model above) - Replay detection -- stNum/sqNum tracking with baseline no-downgrade
- Test-flag blocking -- optionally block test frames
- Retransmission interval validation -- IEC 61850-8-1 mandates a
decay schedule (T0, T1=T02, T2=T12, ..., T_max). Frames arriving with
intervals that materially deviate from the published schedule are flagged
as
AlertCode::RetransmissionAnomaly. - Heuristic time-sync spoofing indicators -- backwards
tfield or implausibly large forward jumps flagAlertCode::TimeSyncSpoofing.
SV (Sampled Values, IEC 61850-9-2)
- Raw-frame parsing --
parse_sv()decodes a wire buffer (EtherType0x88BA, post-VLAN-strip). - smpCnt monotonicity -- backwards step or duplicate flagged as
AlertCode::SvReplay(modulo-65536 wrap-around is correctly accepted). - Sample-rate anomaly -- excessive smpCnt gaps and mismatched
smpRateflagAlertCode::SvRateAnomaly. - IED binding --
svIDregistered to a fixed publisher MAC; mismatch flagsAlertCode::IedMismatch(heuristic; defeated by MAC spoofing). - Heuristic time-sync spoofing indicators -- shared per-IED tracker with GOOSE.
Stack Budget
~3 KiB.
Usage
use vs_iec61850_monitor::{
Iec61850Monitor, MmsFrame, MmsServiceType, GooseFrame, RetxSchedule,
};
use vs_types_ind::SvFrame;
let mut monitor = Iec61850Monitor::new_strict();
// Configure MMS: read-only, allow Read and GetNameList
let mask = (1u16 << MmsServiceType::Read as u8)
| (1u16 << MmsServiceType::GetNameList as u8);
monitor.set_mms_service_mask(mask);
monitor.set_mms_read_only(true);
// Configure GOOSE: allow a specific publisher
monitor
.add_goose_publisher([0x00, 0x11, 0x22, 0x33, 0x44, 0x55], b"")
.unwrap();
// Configure retransmission schedule and time-sync detection
monitor.set_retx_schedule(RetxSchedule::default_8_1(), true);
monitor.set_time_max_forward_jump_s(60);
// Bind an SV publisher MAC to an svID
monitor
.add_sv_publisher([0x00, 0x11, 0x22, 0x33, 0x44, 0x66], b"MU1", 80)
.unwrap();
monitor.set_sv_max_smp_cnt_gap(256);
// Parse a raw SV Ethernet payload and inspect it.
let bytes: &[u8] = &[];
if let Ok(sv) = Iec61850Monitor::parse_sv(bytes, 0) {
let _ = monitor.inspect_sv(&sv);
}
License
Apache-2.0. See LICENSE.