EnOcean Rolling Code PoC Implementierung

Begonnen von JanS, 11 Mai 2014, 19:44:38

Vorheriges Thema - Nächstes Thema

klaus.schauer

#45
Ob der Taster defekt ist, kann ich natürlich schwer einschätzen. Dagegen spricht aber, dass der Taster sauber in der EnOcean DolphinView Advanced angelernt und die verschlüsselten Telegramme dekodiert werden. Dort wird auch automatisch das richtige EEP zugeordnet. Das hat mich auf die Idee mit der festen Anlernprozedur zu EEP D2-03-00 Manufacturer: Multi user Manufacturer ID gebracht.

Hier die Ergebnisse aus DolphinView Advanced

Internals:
   CFGFN
   DEF        FEFF91C3
   IODev      TCM310_0
   NAME       EnO_STE_FEFF91C3
   NOTIFYDEV  global
   NR         49
   STATE      ???
   TYPE       EnOcean
   Readings:
     2014-05-22 06:07:35   rlc             F566
     2014-05-22 06:07:35   teach-in        EEP D2-03-00 Manufacturer: Multi user Manufacturer ID
Attributes:
   IODev      TCM310_0
   dataEnc    VAES
   key        BA3770929CA4633EDF0A8E876793E764
   macAlgo    3
   manufID    7FF
   rlc        F566
   rlcAlgo    2,++
   rlcTX      false
   room       EnOcean
   subType    switch.00

Die Teach-In Daten aus Fhem und dem Analysetool passen m. E. zusammen. Die empfangenen Daten werden dort sauber dekodiert und der RLC hochgezählt.

JanS

#46
Ja wenn Dolphin das sauber entschlüsseln kann, dann spricht das gegen ein Problem mit dem PTM215; jedoch spricht es für ein Problem mit der Spezifikation.
Der EnOcean public key ist beim MAC nicht beteiligt, das ist mir gestern Abend entfallen, also bleibt rein const_Rb oder etwas generelles. Den private Key konntest Du ja mit DolphinView bestätigen.
Die Bitschiebeoperationen scheinen auch nicht das Problem zu sein, sonst könnte ich ja nichts verifizieren oder entschlüsseln.

Da EnOcean mir auf technische Fragen nicht antwortet, können wir aus derzeitiger Sicht das Thema komplett beerdigen; was auch meine "Installation" betrifft.
Totaler Mist, aber besser es jetzt schon zu merken als später. Ich werd mir noch mal andere MAC Implementierungen angucken, ob mir was auffält aber ich habe bei dem Thema wenig Hoffnung.

EDIT: Wenn du Lust hast, kannst du mal meine MAC Implementierung mit http://www.ietf.org/rfc/rfc4493.txt vergleichen, dass ist das was EnOcean sogar in die Spec ge-copy&pasted hat.

JanS

Ich habe gerade den Subkey Teil des Algorithmus gegen die Testvektoren aus dem RFC verglichen: Passt, sprich L, K1 und K2 erstelle ich korrekt, auch in Bezug auf XOR mit const_Rb.
Ich checke nochmal Padding und sonstiges Gelump, allerdings ist das Key unabhängig, sprich es müsste zwangsweise auch bei mir schief gehen. AES(und jeder andere gescheite Algorithmus) hat die nette Eigenschaft, dass bei einem Bit Input Änderung gleich eine ganze Lawine von Output Änderungen entsteht.

klaus.schauer

Ich habe bei EnOcean nachgefragt und auf den Artikel im Forum verwiesen. Leider fällt es den Fachleuten dort schwer, mit den Informationen aus dem Forum, das Problem zu erkennen. Könntest Du Zitat "Kurz die Situation (welche Module mit SW Version) darstellen und wo das Problem liegt oder welche Fragen es gibt."

JanS

Ich implementiere gerade den vollständigen AES-CMAC Algorithmus neu und vergleiche jeden Schritt mit den Testvektoren aus dem RFC (http://www.ietf.org/rfc/rfc4493.txt).
Das ganze packe ich dann in deinen FHEM Code, bzw. teste es mit deinen Daten erneut.
Mein Bauchgefühl ist derzeit, das EnOcean die Subkeys K1 und K2 falsch bzw. nicht nach RFC4493 berechnet, was bei meinem private Key nicht zum tragen kommt, da für diesen keine XOR Operation mit const_rb (0x00000000000000000000000000000087) erforderlich ist.

Ich führe es ASAP hier genauer aus.

JanS

#50
Gut dann mal los, meine Neuimplementierung von AES-CMAC  liefert exakt die gleichen Werte wie mein erster Wurf, und diese Implementierung ist nun gegen die Testvektoren im RFC geprüft und somit zu 100% korrekt.

Welche Module/Software ich benutze, was soll ich dazu sagen???

Ich werde es mal schrittweise hier auflisten, die Entwickler von EnOcean sollten damit eigentlich klarkommen; und auch kommentieren können was nicht korrekt ist.

Für das Teach-In kommen folgende ESP3 Telegramme von deinem PTM215:
55000F07012B35244BF564BA3770929CFEFF91C30001FFFFFFFF4C00B5
5500120701183540A4633EDF0A8E876793E764FEFF91C30001FFFFFFFF4A00B1
Folgende Infos extrahiere ich daraus:
1.) RLC 16bit lang, wird bei jedem Senden inkrementiert und ist 'F564'
2.) Der RLC wird nicht bei jedem Telegram übertragen
3.) Als Verschlüsselung kommt VAES zum Einsatz
4.) Der MAC ist 3Byte lang
5.) Der Private Key lautet "ba3770929ca4633edf0a8e876793e764"

L, K1 und K2 für AES-CMAC müssen für diesen private Key sein:
L  ec82b91d8c3ffb0f4030d266e4080ea2
K1 d905723b187ff61e8061a4cdc8101dc3
K2 b20ae47630ffec3d00c3499b90203a0f


Das sollte von EnOcean mal zuallerrest verifiziert werden, sofern die Infos aus dem Teach-In korrekt sind.

Als Nachrichten von deinem PTM215 kommen:
1.) 55000A0701EB3000A9C8D7FEFF91C30003FFFFFFFF43001D
2.) 55000A0701EB300C05AA94FEFF91C30003FFFFFFFF430039
Ich extrahier daraus folgende Daten:
1.) RORG: 30 DATA: 00 CMAC: A9C8D7 ID: FEFF91C3
2.) RORG: 30 DATA: 0C CNAC: 05AA94 ID: FEFF91C3

Nun versuche ich also den AES-CMAC der ersten Nachricht zum Vergleich zu berechnen und komme auf folgende Ergebnisse:
AES-CMAC über die Daten "3000F564" als RORG+DATA+aktueller RLC (s.o.) mit private Key "ba3770929ca4633edf0a8e876793e764" ergibt "91bca6dfef406f2c10e497235ade13ca".
Der zu verwendendte Teil laut Spezifikation und Teach-in sind die ersten 3Bytes also "91BCA6" was nicht "A9C8D7" entspricht. Somit kann die Nachricht nicht validiert werden.

Da ich meine AES-CMAC Funktion nun schon zum zweiten Mal vollständig implementiert habe, gegen die Testvektoren aus dem RFC verglichen habe UND es mit meinem PTM215 funktioniert, komme ich zu folgendem Schluß:

EnOcean rechnet nicht mit const_Rb 0x00000000000000000000000000000087, welcher für meinen PTM215 Key nicht zum Tragen kommt da MSB von L und K1 0 sind.
ODER dein PTM215 macht etwas falsch. EDIT: Was wir ja vermutlich ausschließen können da DolphinView bei Dir kein Problem hat.

So, ich kann leider unmöglich noch mehr Informationen liefern, nur EnOcean kann noch etwas dazu sagen.
Evtl. kommt heute Nachmittag noch die versprochene FHEM Implementierung, ändert aber nichts am Ergebnis, beide Implementierungen kommen zum selben Ergebnis was den MAC angeht.

JanS

#51
Ich hab den Fehler gefunden! Lag doch an meiner MAC Implementierung, war allerdings so fies, dass er sich bei den Testvektoren selbst rauscancelled. Ich hab bis jetzt nicht verstanden, warum...
Aber egal, füge mal bitte in secure_4.pl hinter Zeile 336 folgende Zeile ein und probiere es erneut:
$k1_bit = unpack('B128', $k1);

EDIT: Für interessierte Mitleser, die Testvektoren des RFCs erzeugen einen Wert L mit nicht gesetztem MSB, dadurch lief mein Code nicht in den Zweig der K1 mit const_Rb XORed. Mein PTM215 nutzt einen private Key, der weder den Codepfad der XOR Operation von K1 noch K2 trifft. Beide Varianten erzeugten somit den einzigen relevanten Subkey K2 korrekt. Nur der private Key von Klaus PTM215 triggerte beide Codepfade und erzeugte somit in Konsequenz einen falschen K2.

Einen Dank an EnOcean, falls sich jemand die Mühe gemacht hat drüber zu schauen!

klaus.schauer

Ich bin froh, dass der Fehler wohl gefunden ist. Ich teste das heute Abend.

JanS

Bislang hat der Fix mit all deinen Logs die genügend Daten zum neu Testen enthielten geklappt, insofern kann man zuversichtlich sein. ;-)

klaus.schauer

#54
Perfekt, super... hier der Beweis:


Internals:
   DEF        FEFF91C3
   IODev      TCM310_0
   LASTInputDev TCM310_0
   MSGCNT     4
   NAME       EnO_STE_FEFF91C3
   NOTIFYDEV  global
   NR         40
   STATE      BI
   TCM310_0_DestinationID FFFFFFFF
   TCM310_0_MSGCNT 4
   TCM310_0_PacketType 1
   TCM310_0_RSSI -67
   TCM310_0_ReceivingQuality excellent
   TCM310_0_RepeatingCounter 0
   TCM310_0_SubTelNum 3
   TCM310_0_TIME 2014-05-22 20:33:42
   TYPE       EnOcean
   Readings:
     2014-05-22 20:23:27   channelA        A0
     2014-05-22 20:33:41   channelB        BI
     2014-05-22 20:33:42   energyBow       released
     2014-05-22 20:33:42   rlc             F5B4
     2014-05-22 20:33:41   state           BI
     2014-05-22 19:37:34   teach-in        EEP D2-03-00 Manufacturer: Multi user Manufacturer ID
Attributes:
   IODev      TCM310_0
   dataEnc    VAES
   key        BA3770929CA4633EDF0A8E876793E764
   macAlgo    3
   manufID    7FF
   rlc        F5B4
   rlcAlgo    2,++
   rlcTX      false
   room       EnOcean
   subType    switch.00


Herzlichen Dank für die Arbeit.

Ich habe noch kleinere Änderungen vorgenommen:

- Die LOGs stehen jetzt auf "debug" >> Bitte mal prüfen, was an LOGs und sonstigen print-Einträgen dauerhaft für eine Fehlersuche bei Supportanfragen drinbleiben soll.

- Die Ausgabeformatierung von EnOcean_sec_convertToNonsecure habe ich zurechtgebastelt. >> Bitte ggf. eine bessere Lösung wählen.

M. E. gibt es jetzt noch zwei Aufgaben:

- Umstellung oder Ablösung des Zusatzpaketes Crypt::Rijndael durch Routinen, die im -hoffentlich- Perl-Grundpaket enthalten sind. Wäre ganz wichtig, damit FHEM auf allen Plattformen insbesondere der FRITZ!Box sofort lauffähig ist.

- Kurze englische Beschreibung der neuen Kryptofunktionen und des Teach-In Verfahrens der PTM 215 für die commandref. Die Beschreibung der neuen Profile "switch.00" und "windowHandle.10" ist schon fertig.

Ich hoffe, dass ich dafür mit Deiner Unterstützung rechnen kann.

P. S. Ich habe rlc jetzt als verstecktes Reading eingerichtet.

JanS

#55
Cool :-)
Gut ich hab den Code noch mal überarbeitet und die MAC Generierung stärker modularisiert. Müsstest Du noch mal kurz checken, da ich das ausschließlich im Editor getan hab.
Ich habe die Debug Ausgaben auf das, im meinen Augen, notwendige Minimum zurechtgestutzt. Die Zukunft wird zeigen ob das reicht. ;-)

ZitatDie Ausgabeformatierung von EnOcean_sec_convertToNonsecure habe ich zurechtgebastelt. >> Bitte ggf. eine bessere Lösung wählen.
Was meinst Du damit? Ich verstehe die Frage nicht.

ZitatUmstellung oder Ablösung des Zusatzpaketes Crypt::Rijndael durch Routinen, die im -hoffentlich- Perl-Grundpaket enthalten sind. Wäre ganz wichtig, damit FHEM auf allen Plattformen insbesondere der FRITZ!Box sofort lauffähig ist.
Das ist ein größeres "Thema". Es gibt ein PP (Pure Perl) Modul namens Crypt::Rijndael_PP das ohne XS bzw. zu kompilierenden Code auskommt. Eine AES Implementierung, welche bei den üblichen Perl Distributionen mitgeliefert wird, gibt es meines Wissens nach nicht. Eine in das FHEM EnOcean Modul zu übernehmen ist "ein wenig" umfangreicher...

ZitatKurze englische Beschreibung der neuen Kryptofunktionen und des Teach-In Verfahrens der PTM 215 für die commandref. Die Beschreibung der neuen Profile "switch.00" und "windowHandle.10" ist schon fertig.
Du meinst etwas in der Art:
--
This module also supports the secure operating mode of PTM215 based switches. To use this, you first have to start the teach in mode via "set TCM teach 600" and then doing the following on the PTM215 module:  1.) Remove the switch cover of the module 2.) Press both buttons of one rocker side (A0&A1 or B0&B1) 3.) While keeping the buttons pressed actuate the energy bow twice. This generates two teach-in telegrams which synchronize the TCM module with the PTM215. Both the FHEM Module and the PTM215 now maintain a counter which is used to generate a rolling code encryption scheme. Also during teach-in, a private key is transmitted to the TCM/FHEM. The counter value is allowed to desynchronize for a maximum of 128 counts, to allow compensating for missed telegrams, if this value is crossed you need to teach-in the PTM215 again. Also if your FHEM installation gets erased including the state information, you need to teach in the PTM215 modules again(which you would need to do anyway). As for the security of this solution, if someone manages to capture the teach-in telegrams, he can extract the private keay of the PTM215 module, so the added security isn't perfect but relies on the fact, that noone listens to you setting up your installation. ;-)
--

klaus.schauer

Danke für den Beschreibungstext. Ich werde ihn in die commandref einbauen.

Ich habe die geänderten Routinen übernommen. Leider sind diese nicht lauffähig. Bei einem angelernten Schalter ergibt sich wieder das gleiche Fehlerbild, wie vor der vorletzten Fassung:


2014.05.26 19:10:51 2: EnOcean EnO_STE_FEFF91C3 security ERROR: Can't verify or decrypt telegram
2014.05.26 19:10:52 2: EnOcean EnO_STE_FEFF91C3 security ERROR: Can't verify or decrypt telegram


Neues Anlernen ist auch fehlerhaft:

Internals:
   CFGFN
   DEF        FEFF91C3
   IODev      TCM310_0
   NAME       EnO_SEC_FEFF91C3
   NOTIFYDEV  global
   NR         51
   STATE      ???
   TYPE       EnOcean
Attributes:
   IODev      TCM310_0
   rlcAlgo    2,++
   room       EnOcean
   subType    SEC



2014.05.26 19:12:10 2: TCM set TCM310_0 teach 60
2014.05.26 19:12:16 1: EnOcean Unknown device with ID FEFF91C3 and RORG SEC, please define it.
2014.05.26 19:12:16 2: autocreate: define EnO_SEC_FEFF91C3 EnOcean FEFF91C3 EnOcean:1:30:0E284EDE:FEFF91C3:00:03FFFFFFFF3500
2014.05.26 19:12:16 2: EnOcean EnO_SEC_FEFF91C3 security ERROR: Secure mode messages without MAC unsupported
2014.05.26 19:12:16 2: autocreate: define FileLog_EnO_SEC_FEFF91C3 FileLog ./log/EnO_SEC_FEFF91C3-%Y.log EnO_SEC_FEFF91C3

Danach geht natürlich nichts mehr.

2014.05.26 19:12:17 2: EnOcean EnO_SEC_FEFF91C3 security ERROR: Secure mode messages without MAC unsupported
2014.05.26 19:12:33 2: EnOcean EnO_SEC_FEFF91C3 security ERROR: Secure mode messages without MAC unsupported

Ich hatte leider in den letzten Tagen keine Zeit, mal einen vertieften Blick auf die Routinen zu werfen.

Die Ausgabeformatierung von EnOcean_sec_convertToNonsecure habe ich zurechtgebastelt.


my $data_end = unpack('H32', $data_dec);
$data_end =~ /^.(.)/;

#print "MSG: $1\n";
return (undef, '32', "0" . uc($1));


Meine Formatierung "0" . uc($1) ist doch wohl eher eine Notlösung. Mir ist nicht klar, was in $data_end enthalten ist.

Wie machen wir mit den Perl Kryptomodulen weiter? Ich würde die neuen Funktionen gerne offiziell verteilen. Nur ohne eine einfache Lösung für Crypt::Rijndael macht das keinen Sinn.

Ich habe eben eine CPAN-Anleitung für die FRITZ!box 7390 gefunden... Falls ich mich entscheiden müsste, würde ich es nicht probieren. Das ist was für Perl-Insider. Für den "Normalnutzer" ist die Hürde zu hoch und das Fehlerrisiko einfach zu groß.

JanS

#57
Wie gesagt, war nur ne schnelle Zusammenstellung aus meinen Tests um das Ganze zu modularisieren; funzt bei mir einwandfei. Evtl. sind ein paar Flüchtigkeitsfehler drinne, musst Du nicht zwangsweise so übernehmen, ist nur optional. Die Routinen sind mittlerweile sehr einfach und verständlich finde ich, dass mache ich jetzt mal von deinem Interesse abhängig, ob der modulare Code drinnen landet oder der "alte". ;-)

Was mich wundert, am Anlern-Code habe ich so bewusst garnichts geschraubt...

ZitatMeine Formatierung "0" . uc($1) ist doch wohl eher eine Notlösung. Mir ist nicht klar, was in $data_end enthalten ist.
Es wird lediglich ein Nibble(4Bit) übertragen, da kann also technisch 0..F drinnen stehen, laut EEP sogar noch weniger.

ZitatWie machen wir mit den Perl Kryptomodulen weiter? Ich würde die neuen Funktionen gerne offiziell verteilen. Nur ohne eine einfache Lösung für Crypt::Rijndael macht das keinen Sinn.
Kryptografie ist nicht "einfach", wenn Du die Zeit hast AES/Rijndael in Perl neu zu implementieren, ich habe sie leider nicht. Und ein Freund von "ich packe alle Räder einfach neu erfunden in meinen Code" bin ich leider auch nicht.
Daher wäre mein Vorschlag ein anderer, wenn Crypt:Rijndael verfügbar ist, dann wird EnOcean Security unterstützt, sonst nicht.

ZitatIch habe eben eine CPAN-Anleitung für die FRITZ!box 7390 gefunden... Falls ich mich entscheiden müsste, würde ich es nicht probieren. Das ist was für Perl-Insider. Für den "Normalnutzer" ist die Hürde zu hoch und das Fehlerrisiko einfach zu groß.
Für die FB würde es dann nicht unterstützt, auf einem normalen Rechner eben schon, evtl. mit den Paket Dependencies abgefrühstückt, da wird eh beim DEB paket was nachgezogen.