Elero: Silent Gliss "Control N" (433.92 MHz) — same framing as `elero.c`, different payload obfuscation
Following on from #3083 and the elero.c decoder: I have a second Silent Gliss system that uses the same Elero framing but at 433.92 MHz, and whose 8-byte obfuscated block does not decode with the substitution table in elero.c.
Posting complete CRC-valid captures with known button labels in case they are useful, and to ask whether anyone recognises the variant.
Device
- Handsets: Silent Gliss SG 11932 (6-channel) / SG 11931 (1-channel), marketed as "SG Control N"
- Blinds: Silent Gliss SG 4970 roller blinds, Series 40 motors (SG 11943 / SG 11944), receiver integrated in the motor
- Silent Gliss is a Nice S.p.A. brand; Nice has owned elero since 2011
This is a different product line from the SG 5600 / 11490 wall switch that elero.c targets.
Radio parameters (confirmed working)
Captured with a CC1101 in packet mode, so the chip does sync detection, de-whitening and CRC. Configuration is the one from andyboeh/esphome-elero, unchanged except the frequency:
433.92 MHz, GFSK, 76.77 kBaud, deviation 34.9 kHz, channel bandwidth 232 kHz
MDMCFG4=0x7B MDMCFG3=0x83 MDMCFG2=0x13 DEVIATN=0x43
SYNC1=0xD3 SYNC0=0x91 PKTCTRL0=0x45 (whitening + CRC + variable length)
FOCCFG=0x1D PKTLEN=0x3CEvery packet below passed the hardware CRC-16 (poly 0x8005, init 0xffff), so framing, whitening and sync are all correct.
Frame layout
Matches elero.c exactly, with 3-byte destination addresses
(dests_len = ndst * 3, as esphome-elero does for typ > 0x60):
[0] len = 0x1D (29) wire length = len + 3
[1] cnt increments per command
[2] typ 0x6A = command from a remote, 0xCA = status from a blind
[3] typ2 0x28
[4] hop 0x00 from the handset, 0x0A from a blind
[5] syst 0x01
[6] chl 1 or 2 in commands; in a status frame, the counter being acked
[7..9] src [10..12] bwd [13..15] fwd
[16] ndst = 1
[17..19] dst 3-byte address
[20..21] p1, p2 = 0x20, 0x00
[22..29] obfuscated block (8 bytes)Addresses seen: handset 1F23C8, blind ch1 7C0BBB, blind ch2 1BE5BA.
How this differs from elero.c
| Field | elero.c (SG 5600/11490) |
This device (Control N) |
|---|---|---|
| Frequency | 868 / 915 MHz | 433.92 MHz |
typ |
0x45 | 0x6A (cmd) / 0xCA (status) |
typ2 |
0x10 | 0x28 |
hop |
0x05 | 0x00 / 0x0A |
chl |
0x11 / 0x22 / 0x03 | 0x01 / 0x02 |
p1, p2 |
0x00, 0x03 | 0x20, 0x00 |
dst |
1-byte channel refs | 3-byte addresses |
The problem
elero.c's elero_decode_command() (identical to
QuadCorei8085/elero_protocol) should yield
00 00 <cmd> 00 00 00 00 <parity>. On these captures it yields no such
structure: byte 2 is never a valid command and bytes 3-6 are never zero.
Captures — bytes 0..29, CRC already verified and stripped
Each group is a separate run where only one button was pressed, so
block[2] should be constant within a group and differ between groups.
Only DOWN pressed (channel 1)
1D 4C 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 98 6D C0 F1 47 6D 2C E8
1D 4D 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 66 D1 A1 A5 32 96 D5 99
1D 4E 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 28 EF 38 44 B2 BF 88 80
1D 4F 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 50 D5 6B B0 60 8A 63 4E
1D 51 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 D6 88 B6 F3 81 C7 A8 04
1D 53 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 CB 46 5B 87 6D 22 35 B4
1D 54 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 48 27 23 6F 47 74 26 B3
1D 55 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 7B C0 48 2A E3 76 02 25
1D 58 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 E9 21 E9 0D A1 43 58 D8
1D 59 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 61 3E 7B DC 54 48 42 69
1D 5A 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 31 D7 3B E3 21 BB 48 87Only STOP pressed (channel 1)
1D 62 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 DE 21 81 83 CB BE 89 21
1D 64 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 25 DB 5B B8 39 24 85 08
1D 65 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 95 10 A7 07 9F 70 24 B6
1D 66 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 9B 0B 9C F9 AC D3 7E 9C
1D 67 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 36 AB AF 97 D6 78 0A 7B
1D 69 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 40 8A E8 EC 15 14 8F 44
1D 6B 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 11 6E CD 20 95 75 E7 12
1D 6C 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 97 A8 43 1D D7 B1 80 8C
1D 70 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 30 C7 4F A9 23 FD 2D 65Only the Up+Down combination (recalls the stored intermediate position)
1D 73 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 C2 AE 08 2B F1 5B 2F B9
1D 74 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 58 B9 24 42 78 04 6C 14
1D 75 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 C4 D3 BA 27 07 19 FA B7
1D 76 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 CD 75 A3 B2 81 66 73 A0
1D 77 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 E0 2A FD 44 C6 9B FC C3
1D 78 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 8E 46 EF 91 EC 5B 91 E3
1D 7A 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 5A BB 40 5D 3B 44 5A 3B
1D 7B 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 46 FD 5E 4F 90 1F 11 D3Status frames from blinds (typ=0xCA)
1D 53 CA 28 0A 01 28 7C 0B BB 7C 0B BB 1F 23 C8 01 1F 23 C8 20 00 8E 54 C1 18 E5 9D 01 8B
1D 54 CA 28 0A 01 29 7C 0B BB 7C 0B BB 1F 23 C8 01 1F 23 C8 20 00 3C 9A BD A6 FF 3F 96 2A
1D EC CA 28 0A 01 2C 1B E5 BA 1B E5 BA 1F 23 C8 01 1F 23 C8 20 00 FE 0A 78 E4 5C 90 B6 E8Already ruled out
To save anyone repeating them:
elero.c/elero_protocolalgorithm as-is, at every plausible block offset (17-24). Scored on how many of bytes 3-6 decode to zero: best was 0.07 out of 4.Brute force of both decrementing-key seeds (all 65,536 combinations at decrement 0x22), requiring bytes 3-6 to decode to zero. No hit.
A difference attack that removes every unknown except the table. Bytes 3 and 5 share key
k1; bytes 4 and 6 sharek0. Differencing between packet pairs cancels the per-message key and the decrementing-key constants, leaving pure constraints on the substitution table:Q(Rp[3]) ^ Q(Rq[3]) == Q(Rp[5]) ^ Q(Rq[5]) Q(Rp[4]) ^ Q(Rq[4]) == Q(Rp[6]) ^ Q(Rq[6])1418 such constraints from 28 packets, covering all 16 table entries. No consistent permutation exists.
Attack 3 is assumption-light — it does not depend on the key constants at all — so its failure suggests the difference is structural, not merely a different table substituted into the same algorithm.
Also tested on the live blind: replay does not work. Verbatim replay of a
captured command, and replay with the plaintext cnt byte changed to unused
values, were both ignored (transmission independently verified: TX FIFO
draining and MARCSTATE entering TX).
The ask
Does anyone recognise this variant, or see something wrong in the assumptions
above? Happy to capture whatever would help — more labelled runs, other
buttons, other channels, or raw IQ with -Y minmax once my RTL-SDR arrives.
Source: merbanan/rtl_433