Silver Spring Networks Protocol: Difference between revisions
Added more information about the Itron/SSN traffic |
Add fixed-AMI NIC 511 variant: framing, degree-9 whitening (the "Mask" transform), CRC-32, 87-channel plan, hop sequence; distinct from the drive-by/water variant |
||
| Line 56: | Line 56: | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
== Fixed-AMI variant (Aclara I-210+c / NIC 511) == | |||
Transport-layer documentation for the Silver Spring mesh format used by an Aclara | |||
I-210+c meter with a NIC 511 module on a fixed AMI network (passive RTL-SDR | |||
capture). The application payload is AES-CCM* encrypted; everything below is the | |||
transport layer. | |||
This is a distinct on-air format from the other Silver Spring work — there are at | |||
least three, with different sync words and scramblers: | |||
{| class="wikitable" | |||
! Source !! Sync / SFD !! Scrambler !! CRC | |||
|- | |||
| This page's capture (<code>…008C900A</code>) || post-preamble <code>de 9d 27 27 16 66 f0 6c</code> || — || — | |||
|- | |||
| rtl_433 <code>silver_spring_mesh</code> (drive-by/water) || <code>SFD 0xF3A0</code>, 3-byte PHR || 8-bit <code>x⁸+x⁴+x³+x²+1</code> || CRC-32/MPEG-2, 4-byte FCS | |||
|- | |||
| This variant (fixed-AMI NIC 511) || <code>0C 5F <ch> FF</code>, 2-byte inverted PHR || degree-9 <code>x⁹+x⁸+x⁵+x²+1</code> || CRC-32, 1-byte trailer | |||
|} | |||
The 8-bit and degree-9 scramblers are provably different: the 8-bit scrambler | |||
descrambles no NIC 511 frame at any of its 255 seeds, and Berlekamp–Massey gives | |||
the NIC 511 keystream linear complexity 9 (an 8-bit LFSR is ≤ 8). | |||
=== Summary === | |||
{| class="wikitable" | |||
! Layer !! Result | |||
|- | |||
| Modulation || 2-GFSK, h≈0.5, 100/150/200 kBd (per-frame) | |||
|- | |||
| PHY header || <code>0C 5F <channel> FF</code>; channel = 255 − byte 2 | |||
|- | |||
| Channel plan || 87 channels, <code>f(N) = 902.2990 MHz + 299.991 kHz·N</code>, 300 kHz spacing | |||
|- | |||
| Whitening || degree-9 LFSR <code>x⁹+x⁸+x⁵+x²+1</code>, recovered by Berlekamp–Massey | |||
|- | |||
| Integrity || CRC-32 (poly 0x04C11DB7, MSB-first, init 0); trailer = MSB(crc) ⊕ K[len] | |||
|- | |||
| Framing || length-keyed header grammar; every byte of 12 length classes accounted for | |||
|- | |||
| Flags byte || <code>base(channel) ⊕ frame-type</code> (0=broadcast, 2=unicast, 3=beacon) | |||
|- | |||
| Beacon timing || 120.000 s lattice, phase σ = 0.25 s over 450+ cycles | |||
|- | |||
| Hop sequence || channel = f(slot mod 83), 153/153 forward predictions | |||
|- | |||
| Topology || dual-homed relay → two EUI-64 access points → head-end (see [[Silver Spring Networks Relay]], [[Silver Spring Networks Access Point]]) | |||
|- | |||
| Payload || AES-CCM* encrypted, not recovered | |||
|} | |||
=== PHY and channel === | |||
2-GFSK, modulation index ≈ 0.5, 100/150/200 kBd. The 4-byte block after the | |||
preamble is not a sync word: bytes 0/1/3 are fixed (<code>0C 5F .. FF</code>) and | |||
byte 2 is the channel, <code>N = 255 − X</code>. Carrier vs. N: | |||
f(N) = 902.2990 MHz + 299.991 kHz · N N = 0..86 (87 channels, 300 kHz) | |||
Residuals < 2 kHz per channel. This differs from the FCC filing's 64 channels / | |||
400 kHz (that filing is a different, earlier module). | |||
=== Whitening === | |||
The PSDU is whitened by a degree-9 LFSR: | |||
b[n] = b[n-1] ^ b[n-2] ^ b[n-5] ^ b[n-8] ^ b[n-9] period 255 | |||
Recovered by Berlekamp–Massey over the all-zero payload padding of long frames | |||
(that region is raw keystream on the air; linear complexity comes out to 9). | |||
Plaintext bytes 0–4 are the constant serial prefix <code>00 13 50 05 00</code>, | |||
so the mask for any frame is <code>cipher[0:5] ^ prefix</code> (40 bits) extended | |||
by the recurrence — no per-frame seed needed. | |||
=== Integrity === | |||
The trailing byte is the top byte of a CRC-32 (poly <code>0x04C11DB7</code>, | |||
MSB-first, init 0) over the de-whitened frame, XORed with a per-length constant: | |||
K = {9:0x78, 12:0x0E, 14:0x5B, 16:0x7A, 21:0xEB, 22:0xE8, 29:0x05, | |||
55:0xA6, 111:0x7D, 112:0x2D, 134:0x6E, 213:0x60} | |||
Validates on ~98% of frames (2816/2880 across the corpus); failures carry bit | |||
errors visible as nonzero bytes in known-zero padding. | |||
=== Framing === | |||
frame := SRC(8) [DST(8)] {headers} payload TRAILER(1) | |||
ln= 12 SRC | 04 81 xx | TRAILER | |||
ln= 14 SRC | 01 03 aa bb cc | TRAILER | |||
ln= 22 SRC | DST | 01 03 aa bb cc | TRAILER | |||
ln= 29 SRC | DST | 01 03 .. | PAYLOAD(7) | TRAILER | |||
ln= 55 SRC | 01 03 .. | 04 81 xx | PAYLOAD(38) | TRAILER | |||
ln=111 SRC | 01 80 | 00 82 .. | PAYLOAD(96) | TRAILER (beacon) | |||
ln=213 SRC | 00 82 .. | 01 03 .. | PAYLOAD(195) | TRAILER (encrypted) | |||
Addresses: 8 bytes, OUI <code>00:13:50</code>. Endpoints serial-form | |||
(<code>00:13:50:05:00:xx…</code>); access points EUI-64 | |||
(<code>00:13:50:FF:FE:60:xx…</code>, see [[Silver Spring Networks Access Point]]). PHR byte 2 = <code>base(channel) ⊕ | |||
frame-type</code>, type ∈ {0 broadcast, 2 unicast, 3 beacon}. | |||
=== Beacon timing and hopping === | |||
The relay node beacons on a 120.000 s lattice (phase σ 0.25 s over 450+ cycles). | |||
By slot index, channel = <code>slot mod 83</code> (verified by 153/153 strictly | |||
causal forward predictions, permutation null 0/3000). Cycle = 83 × 120 s ≈ 2h46m. | |||
=== Payload === | |||
<code>ln=213</code> payloads are 195 bytes of uniform, zero-free, incompressible | |||
data (full linear complexity under Berlekamp–Massey — not a linear scrambler, | |||
unlike the whitened classes). This is AES-CCM* encryption (Itron/Certicom Suite | |||
B). The key is provisioned by the head-end key manager and held in the meter's | |||
secure element, not derivable from the air. | |||
=== References === | |||
* Reproducible code and full write-up: [https://github.com/bash-tilde/silverspring-ami-rf github.com/bash-tilde/silverspring-ami-rf] | |||
* rtl_433 <code>silver_spring_mesh.c</code> (Benjamin Larsson) — the drive-by/water variant | |||
Latest revision as of 20:48, 31 August 2026
Data capture from a Silver Spring Networks smart meter that was initially powered on. The text is very wide so open the file in a text editor, it won't look right in the browser most likely.
Initial capture of data - small file
Silver_Spring_Networks_Smart_Meter_00135005008C900A.txt
170 samples sorted by "Mask" column, notice the data appears similar for each mask, need to figure out how it's being transformed.
Silver_Spring_Networks_Extended_Parsed_02-22-2022_00135005008C900A.txt
Capturing Itron/SSN traffic
In 2012 a permissive change was filed at the FCC to certify and document an RF mode not initially supported. Specifically, it uses 2-FSK over 64 channels from 902.4MHz to 927.6MHz (inclusive) and a data rate of 150kbps. This appears to be the predominantly used mode today among such devices. A summary of all modes of FCC ID SK9AMI7 are shown below.
| Modulation | Frequency range (MHz) | Number of channels | Channel separation (kHz) | Data rates supported (kbps) |
|---|---|---|---|---|
| FSK | 902.25 - 927.75 | 52 | 500 | 19.2 |
| FSK | 902.25 - 927.75 | 52 | 500 | 152.3 |
| OOK | 909.6 - 921.8 | 50 | 200 | 16.4 |
| FSK | 902.4 - 927.6 | 64 | 400 | 150.0 |
The following capture file was created using this gnuradio file. It has the 64 channels explicitly listed within the Center Freq Estimation block. It uses a syncword of 0xAAAAAAAA (which is probably too short) and makes the assumption that data is transmitted most significant bit first, but this is an unverified guess. No checking is done of the packets, so there are very likely to be many packets with errors. In looking through this capture file, the majority of packets start with
aa aa aa aa aa aa aa aa de 9d 27 27 16 66 f0 6cFor that reason, it's likely that those packets are probably mostly correct, while the others should be viewed with suspicion.
File:Meter data capture.grc.txt
File:Raw itron packet dump.zip
Fixed-AMI variant (Aclara I-210+c / NIC 511)
Transport-layer documentation for the Silver Spring mesh format used by an Aclara I-210+c meter with a NIC 511 module on a fixed AMI network (passive RTL-SDR capture). The application payload is AES-CCM* encrypted; everything below is the transport layer.
This is a distinct on-air format from the other Silver Spring work — there are at least three, with different sync words and scramblers:
| Source | Sync / SFD | Scrambler | CRC |
|---|---|---|---|
This page's capture (…008C900A) |
post-preamble de 9d 27 27 16 66 f0 6c |
— | — |
rtl_433 silver_spring_mesh (drive-by/water) |
SFD 0xF3A0, 3-byte PHR |
8-bit x⁸+x⁴+x³+x²+1 |
CRC-32/MPEG-2, 4-byte FCS |
| This variant (fixed-AMI NIC 511) | 0C 5F <ch> FF, 2-byte inverted PHR |
degree-9 x⁹+x⁸+x⁵+x²+1 |
CRC-32, 1-byte trailer |
The 8-bit and degree-9 scramblers are provably different: the 8-bit scrambler descrambles no NIC 511 frame at any of its 255 seeds, and Berlekamp–Massey gives the NIC 511 keystream linear complexity 9 (an 8-bit LFSR is ≤ 8).
Summary
| Layer | Result |
|---|---|
| Modulation | 2-GFSK, h≈0.5, 100/150/200 kBd (per-frame) |
| PHY header | 0C 5F <channel> FF; channel = 255 − byte 2
|
| Channel plan | 87 channels, f(N) = 902.2990 MHz + 299.991 kHz·N, 300 kHz spacing
|
| Whitening | degree-9 LFSR x⁹+x⁸+x⁵+x²+1, recovered by Berlekamp–Massey
|
| Integrity | CRC-32 (poly 0x04C11DB7, MSB-first, init 0); trailer = MSB(crc) ⊕ K[len] |
| Framing | length-keyed header grammar; every byte of 12 length classes accounted for |
| Flags byte | base(channel) ⊕ frame-type (0=broadcast, 2=unicast, 3=beacon)
|
| Beacon timing | 120.000 s lattice, phase σ = 0.25 s over 450+ cycles |
| Hop sequence | channel = f(slot mod 83), 153/153 forward predictions |
| Topology | dual-homed relay → two EUI-64 access points → head-end (see Silver Spring Networks Relay, Silver Spring Networks Access Point) |
| Payload | AES-CCM* encrypted, not recovered |
PHY and channel
2-GFSK, modulation index ≈ 0.5, 100/150/200 kBd. The 4-byte block after the
preamble is not a sync word: bytes 0/1/3 are fixed (0C 5F .. FF) and
byte 2 is the channel, N = 255 − X. Carrier vs. N:
f(N) = 902.2990 MHz + 299.991 kHz · N N = 0..86 (87 channels, 300 kHz)
Residuals < 2 kHz per channel. This differs from the FCC filing's 64 channels / 400 kHz (that filing is a different, earlier module).
Whitening
The PSDU is whitened by a degree-9 LFSR:
b[n] = b[n-1] ^ b[n-2] ^ b[n-5] ^ b[n-8] ^ b[n-9] period 255
Recovered by Berlekamp–Massey over the all-zero payload padding of long frames
(that region is raw keystream on the air; linear complexity comes out to 9).
Plaintext bytes 0–4 are the constant serial prefix 00 13 50 05 00,
so the mask for any frame is cipher[0:5] ^ prefix (40 bits) extended
by the recurrence — no per-frame seed needed.
Integrity
The trailing byte is the top byte of a CRC-32 (poly 0x04C11DB7,
MSB-first, init 0) over the de-whitened frame, XORed with a per-length constant:
K = {9:0x78, 12:0x0E, 14:0x5B, 16:0x7A, 21:0xEB, 22:0xE8, 29:0x05,
55:0xA6, 111:0x7D, 112:0x2D, 134:0x6E, 213:0x60}
Validates on ~98% of frames (2816/2880 across the corpus); failures carry bit errors visible as nonzero bytes in known-zero padding.
Framing
frame := SRC(8) [DST(8)] {headers} payload TRAILER(1)
ln= 12 SRC | 04 81 xx | TRAILER ln= 14 SRC | 01 03 aa bb cc | TRAILER ln= 22 SRC | DST | 01 03 aa bb cc | TRAILER ln= 29 SRC | DST | 01 03 .. | PAYLOAD(7) | TRAILER ln= 55 SRC | 01 03 .. | 04 81 xx | PAYLOAD(38) | TRAILER ln=111 SRC | 01 80 | 00 82 .. | PAYLOAD(96) | TRAILER (beacon) ln=213 SRC | 00 82 .. | 01 03 .. | PAYLOAD(195) | TRAILER (encrypted)
Addresses: 8 bytes, OUI 00:13:50. Endpoints serial-form
(00:13:50:05:00:xx…); access points EUI-64
(00:13:50:FF:FE:60:xx…, see Silver Spring Networks Access Point). PHR byte 2 = base(channel) ⊕
frame-type, type ∈ {0 broadcast, 2 unicast, 3 beacon}.
Beacon timing and hopping
The relay node beacons on a 120.000 s lattice (phase σ 0.25 s over 450+ cycles).
By slot index, channel = slot mod 83 (verified by 153/153 strictly
causal forward predictions, permutation null 0/3000). Cycle = 83 × 120 s ≈ 2h46m.
Payload
ln=213 payloads are 195 bytes of uniform, zero-free, incompressible
data (full linear complexity under Berlekamp–Massey — not a linear scrambler,
unlike the whitened classes). This is AES-CCM* encryption (Itron/Certicom Suite
B). The key is provisioned by the head-end key manager and held in the meter's
secure element, not derivable from the air.
References
- Reproducible code and full write-up: github.com/bash-tilde/silverspring-ami-rf
- rtl_433
silver_spring_mesh.c(Benjamin Larsson) — the drive-by/water variant