EnOcean Rolling Code PoC Implementierung

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

Vorheriges Thema - Nächstes Thema

klaus.schauer

Ich habe jetzt erst einmal einen doppelten Boden für rlc eingebaut. Der Wert wird nun als Attribut und Reading gespeichert und jeweils der größte Wert verwendet. Das Speichern der Attribute in der Konfigurationsdatei muss explizit angestoßen werden und kann deshalb nach einem Neustart veraltet sein. Durch die zweifache Speicherung sollte aber der jeweils aktuelle Wert auch einen (unvorhergesehenen) Fhem Neustart überstehen.

Ich habe den Schalter mehrfach in Fhem neu angelernt. Der Fehler beim Empfang der Datentelegramme tritt sofort nach dem Anlernen auf. Mir ist aufgefallen, dass rlc bei jedem empfangenen Telegramm um 0x102 hochgezählt wird! Ist das ok? In der Routine EnOcean_sec_getRLC($) wird doch immer nur um 1 erhöht.

Beim Anlernen kann es passieren, dass das zweite Telegramm bei schlechten Empfangsverhältnissen nicht ankommt. In diesen Fällen wäre m. E. gut, wenn eine Fehlermeldung wegen eines falschen Keys erzeugt würde.

Ich werde mir die Routinen mal in aller Ruhe ansehen, vielleicht fällt mir was auf.


JanS

#31
ZitatIch habe jetzt erst einmal einen doppelten Boden für rlc eingebaut. Der Wert wird nun als Attribut und Reading gespeichert und jeweils der größte Wert verwendet. Das Speichern der Attribute in der Konfigurationsdatei muss explizit angestoßen werden und kann deshalb nach einem Neustart veraltet sein. Durch die zweifache Speicherung sollte aber der jeweils aktuelle Wert auch einen (unvorhergesehenen) Fhem Neustart überstehen.
Ja das ist ein Muss, der RLC muss stets dem im Sender entsprechen.

ZitatIch habe den Schalter mehrfach in Fhem neu angelernt. Der Fehler beim Empfang der Datentelegramme tritt sofort nach dem Anlernen auf. Mir ist aufgefallen, dass rlc bei jedem empfangenen Telegramm um 0x102 hochgezählt wird! Ist das ok? In der Routine EnOcean_sec_getRLC($) wird doch immer nur um 1 erhöht.
Das ist schräg, du liegst richtig, der Wert sollte nur um 1 erhöht werden, und zwar mit jedem empfangenen Telegram für diesen Schalter.
EDIT: Und bis zu +128 dezimal wenn der RLC gesucht wird, also die Counter auseinander gelaufen sind, aber 258 passt nicht so ganz ins Konzept. Er könnte am Ende bei +255 landen, wenn press und release nicht gematcht haben, dann speicherst du aber vermutlich einen falschen RLC von Anfang an.
Evtl macht das sprinttf im getRLC Ärger, das ist mir schon lange ein Dorn im Auge.
So ausm Bauch raus kannst du mal Zeile 272 durch
readingsSingleUpdate($hash, "rlc", unpack('H4',pack('n', $new_rlc)), 0);
ersetzen und Zeile 281 durch
readingsSingleUpdate($hash, "rlc", unpack('H6',pack('N', $new_rlc)), 0);
EDIT: Und 273, 282 analog dazu.
Macht bei mir komischerweise keinen Ärger, aber wer weiss.

ZitatBeim Anlernen kann es passieren, dass das zweite Telegramm bei schlechten Empfangsverhältnissen nicht ankommt. In diesen Fällen wäre m. E. gut, wenn eine Fehlermeldung wegen eines falschen Keys erzeugt würde.
Gute Idee, da der Key immer 16byte (32 HEX Zeichen) lang sein sollte, kann man da leicht einen Check einbauen.

klaus.schauer

Mit den "etwas angepassten" Änderungen hat sich am Ergebnis nichts geändert. Die Parameter von pack und unpack sollten so richtig sein, aber bitte zur Sicherheit prüfen.

Beim wiederholten Anlernen wird richtig hochgezählt: F53E ... F540. Nach einem Telegramm ist rlc aber wieder F642.

JanS

#33
ZitatBeim wiederholten Anlernen wird richtig hochgezählt: F53E ... F540. Nach einem Telegramm ist rlc aber wieder F642.
Der RLC wird im ersten Teach-In Telegram übertragen, angenommen F53E.
Hochgezählt wird dann nach Empfang des ersten Nicht-Teach-In Telegrams, d.h. beim ersten normalen Tastendruck. Kann der MAC nicht verifiziert werden wird der RLC bis zu 128 Werte weitergezählt.
Da zwei Telegramme versendet werden (Drücken&Loslassen) also max 256.
Während dem Teach-In darf da nichts hochgezählt werden, du sollest den RLC auch im ersten Teach in Telegram sehen können, er startet mit dem dritten Byte.
Das sah in deinen Logs auch gut aus.

Ohne zusätzliche Debug Ausgaben ist das nicht zu finden, ich hing da auch ne Weile dran ;-) Ist sicher was ganz blödes...

EDIT: Zu 258 fällt mir ein 258=256+2, das wären zwei normale Aufrufe plus zwei nicht matchende Aufrufe, wird aufgrund irgendeines Fehler die Dekodierroutine mehrfach aufgerufen mit falschen Daten? Wie oft hast du den Taster betätigt, in Telegrammen gezählt?

klaus.schauer

Das LOG bildet eine komplette Tastenbetätigung ab. Bei einer Tastenbetätigung kommen ja immer zwei Telegramme z. B. BI und release.

Könntest Du mir die Stellen kennzeichnen, die geloggt werden sollen? Dann würde ich die entsprechenden Befehle einbauen.

JanS

#35
ZitatDas LOG bildet eine komplette Tastenbetätigung ab. Bei einer Tastenbetätigung kommen ja immer zwei Telegramme z. B. BI und release.
Ich sehe derzeit einfach keine Möglichkeit wie zwei Telegramme eine Erhöhung des RLC um den Wert 258 bewirken können, 256 ja aber 258?
Das ist keine schrecklich komplizierte Sache und in der Regel liegt die Lösung auf der Hand, bin einigermaßen ratlos, wie sich dieses Verhalten erklären lassen sollte ohne dass EnOcean_sec_convertToNonsecure mindestens vier mal aufgerufen wird bzw. EnOcean_sec_convertToNonsecure eben 258 mal.
EDIT: Bin hinter die 258 gekommen, die routine zählt von 0 bis 128 nicht von 1, insofern passt das mit der Anzahl, bleibt die Frage warum kein passender MAC gefunden wird.

ZitatKönntest Du mir die Stellen kennzeichnen, die geloggt werden sollen? Dann würde ich die entsprechenden Befehle einbauen.
Ich brauche zum debuggen folgendes:
1.) Die rohen ESP3 Telgramme von Teach-In und Tastenbetätigung/release.
2.) Darauf folgend die Ausgabe der Nachricht und der MAC, da gibt es ein paar print Statements in der Routine EnOcean_sec_convertToNonsecure.
#print "DATA: $data_enc\n";
#if ($expect_rlc == 1) { print "RLC: $rlc\n";};
#print "MAC: $mac\n";

3.) In EnOcean_sec_getRLC alle print Statements.
4.) In EnOcean_sec_generateMAC
#print "Calculating MAC for data $data\n";
#print "CMAC ".unpack('H32', $cmac)."\n";


Das sollte fürs Erste reichen und auch gleich einigermaßen aufzeigen, was wie oft aufgerufen wird.


klaus.schauer

Die Ein- und Ausgabeparameter von EnOcean_sec_convertToNonsecure($$$) waren noch etwas strubbelig. Trotzdem ging es den Änderungen immer noch nicht, siehe LOG.

Warum wird MAC über $rorg.$data_enc.$rlc berechnet?

JanS

Ich vermisse im Log irgendwie den zweiten Teil des Teach-Ins, ist da was abhanden gekommen? Würde erklären warum nix geht ;-)

Ansonsten sieht das vom Rest her recht gut aus, kannst du bitte in Zeile 365 noch
Log3 undef, 2, "EnOcean_sec_generateMAC cutted CMAC ".unpack('H32', $1);
einbauen?
RLC, Input für MAC ist alles i.O. Output des MAC Algorithmus checken wir noch.
Hmm evtl. noch in Zeile 300
Log3 undef, 2, "EnOcean_sec_generateMAC private key ".unpack('H32', $private_key);
einbauen

ZitatWarum wird MAC über $rorg.$data_enc.$rlc berechnet?
Weil es in "Security of EnOcean Radio Networks" Kapitel 4.3.8.1 so steht. ;-)
Spaß beiseite, DATA und RLC macht noch Sinn, warum die Jungs den RORG drinne haben wollen ist mir auch nicht klar. Statische Daten erhöhen da jetzt nicht signifikant die Entropie des MACs.
Aber seis drum, wird laut Spec so gemacht und gut ist. ;-)

klaus.schauer

Das Teach-In ist bei dem gesendeten LOG tatsächlich nicht vollständig. Der Fehler trat aber auch bei einem vorherigen Test mit vollständigem Key auf. Dort fehlte aber noch eine LOG-Zeile. Ich mache nochmals einen Test mit den zusätzlichen LOG-Zeilen.

JanS

#39
Ok, merkwürdig, wenn ich alle Telegramme sehe dann kann ich noch mehr sagen, aber eigentlich sieht das alles gut aus :-(
EDIT: Die originalen Telegramme wären noch praktisch, wenn uns bald die Ideen ausgehen ;-)

klaus.schauer

So jetzt habe ich wieder alles zusammen. Habe auch noch eine Plausibilitätsabfrage für "key" eingebaut.

JanS

Ok, abgesehen davon dass ich die zweite Ausgabe der MAC vehunzt habe, was nicht weiter wild ist, sehe ich absolut nicht den Fehler.
Ich werde da Morgen noch mal in Ruhe drüber schauen, und es ggf. Abends einfach mal durch meinen Code laufen lassen.
Das ist gerade extrem mysteriös, ich habe das sogar mal auf nem PI getestet, d.h. Endian Fehler dürften es auch nicht sein.
Getestet habe ich auf nem 32bit x86 und nem PI, worauf hast Du das für diesen Log getestet?

JanS

#42
Hat mir doch keine Ruhe gelassen, habs eben auf die Schnelle mal durch meinen Code gejagt....
Jetzt wirds allerdings schräg, ich kann es auch nicht dekodieren....
Von wann ist dein PTM215?
Wo gekauft?
Wo drin verbaut?

Entweder ist der buggy, oder er verwendet einen anderen Public Key?
Beides ist beunruhigend...

EDIT: Oder mein Mac Algo hat nen Fehler, ich guck morgen mal in Ruhe

klaus.schauer

Ich wars nicht. Der Taster ist aus einem EDK 350 Kit, den ich im August 2013 erhalten habe.

JanS

Wie gesagt bin vollkommen ratlos, der MAC Algorithmus kanns auch nicht sein, es sei denn die Spezifikation von EnOcean ist falsch. Die Operationen sind alle sauber, dein privtae Key erfodert im Gegensatz zu meinem das XORen mit cons_Rb gemäß Spec und das ist auch stimmig als 0x00..87. Da hat EnoCean nichts neues erfunden. XORen tue ich an vielen Stellen, das passt also auch...

Die naheliegendste Vermutung ist derzeit, dass dein PTM215 irgendwie anders tickt als meiner, evtl. ein "Vorserienmodell". Oder eben EnOcean verwendet einen andere const_Rb Wert als in der Spec angegeben.
Beides ist unmöglich herauszufinden, willkommen in der Welt der Kryptographie.
Einzige Idee aktuell, versuch einen neueren PTM215, meiner ist von diesem Monat und  in einem Eltako FMH4 zu Hause.