Probleme mit Security/SendStack/WakeUp

Begonnen von A.Harrenberg, 04 Februar 2017, 14:06:59

Vorheriges Thema - Nächstes Thema

A.Harrenberg

Hallo,

in letzter Zeit gibt es häufiger Auffälligkeiten in denen der "secUnlock" Timer auftaucht. Dieser Timer steht im Zusammenhang mit zwei internen Funktion, secStart() und secEnd(), welche den Sendstack "sperren" solange gerade eine verschlüsselte Kommunikation läuft. Der Ablauf ist leider nicht völlig robust implementiert, bei Übertraungsproblemen kann es dazu kommen das diese Sperre nicht mehr gelöst wird, was der Timer dann erledigt. Dabei bleibt allerdings der alte Befehl auf dem internen Stack liegen, wodurch in der Folge die Kommunikation unter Security "asynchron" wird, dh. statt eines neuen Befehls wird dann dieser alte abgearbeitet und der neue bleibt liegen.

Dieses Problem wollte ich mir eigentlich ansehen und lösen....

Getestet habe ich mit einem AEOTEC Multisensor (als WakeUp-Gerät), dabei sind dann allerdings noch ganz andere/neue Probleme aufgetreteten.

Bei dem Sensor ist die Battery-Klasse auch verschlüsselt, d.h. wenn man den Status abfragen will muss vorher eine "Nonce" vom Sensor geholt werden mit der die Abfrage verschlüsselt werden muss.

Wenn man jetzt (bei schlafendem Sensor) "get Battery" abfragt wird secStart() aufgerufen, der Befehl wird auf einem security-Stack zwischengelagert und es wird ein get nonce Befehl auf dem SendStack abgelegt. Der Befehl bleibt da erst mal liegen, da es ja ein WakeUp-Gerät ist.

Das eigentliche Problem tritt jetzt auf falls der Sensor z.B. eine Bewegung (verschlüselt) melden will. Hierzu fordert er vom Controller eine Nonce an, diese wird generiert und auf den SendStack gelegt, aber nicht versendet, da jetzt zwei Nachrichten auf dem Stack liegen und der Ablauf dadurch aktuell nicht gestartet wird.

Erst wenn eine (unverschlüsselte) WUN vom Sensor kommt wird der Stack "angetriggert" und die Nachrichten werden verschickt. Da hier jedoch jede Menge alte ungültig gewordene Nonce dabei sind werden die meisten Kommunikation fehlschlagen.

Ich hatte schon ein wenig angefangen was am Ablauf zu ändern indem ich bei eintreffen eines get-Nonce den Stack antriggere, das ist aber nicht richtig, das führt dazu das dann alle Befehle des Stacks abgearbeitet werden, obwohl das Gerät ja noch gar keine WUN verschickt hat und die Befehle dadurch je nach Gerät ignoriert werden.

Das ganze hebelt dann auch die oben beschrieben Funktionen secStart() und secEnd() aus, sodaß während einer verschlüsselten Kommunikation weitere Befehle verschickt werden und es zu weiteren Übertragungsproblemen kommt.

Bei einem anderen Testobjekt (BeNext RFID-TagReader 500) ist selbst die WakeUp-Klasse verschlüsselt, wodurch hier auch für die WUN eine Nonce vom Controller angefordert werden muss. Das schlägt dann genauso fehl wie im Beispiel das get Battery, bei dem Gerät kommt man dadurch aber gar nicht mehr aus diesem DeadLock raus.  :(

Soweit eigentlich erst einmal nur zur Info falls jemand Probleme mit Security bei WakeUp-Geräten hat.

Ich habe das Problem bereits mit Rudi kurz andiskutiert, er hat vorgeschlagen die ganzen Sonderbehandlungen für verschlüsselte Nachrichten in den Code vom Stack zu verlagern. Ich schaue mir gerade die Abläufe noch mal genau an und prüfe ob sich das so wie von ihm vorgeschlagen umsetzten lässt.

Die weitere Diskussion zu dem Problem und der Änderung am SendStack wird dann hier geführt werden.

Gruß,
Andreas.

FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

buspirat

Hi Andreas,

Zitat von: A.Harrenberg am 04 Februar 2017, 14:06:59
Das eigentliche Problem tritt jetzt auf falls der Sensor z.B. eine Bewegung (verschlüsselt) melden will. Hierzu fordert er vom Controller eine Nonce an, diese wird generiert und auf den SendStack gelegt, aber nicht versendet, da jetzt zwei Nachrichten auf dem Stack liegen und der Ablauf dadurch aktuell nicht gestartet wird.
folgende Idee: Der SendStack weiß ja, daß der auf die nächste WUN warten muss.
Könnte man die Anfrage nach der Nonce ganz oben auf den Stack legen?

Die anderen Befehle sollten natürlich nur abgearbeitet werden, sobald die WUN kommt.
Eventuell kann man hierfür eine Barriere zusätzlich auf den SendStack legen.

Lustig wird es nur, sobald die Anfrage nach der Nonce und die WUN
halbwegs zeitgleich reinkommen. Dann sollte Dein neuer Code greifen,
daß bis zu xx Nonces kurzzeitig gleichzeitig aktiv seien dürfen.

VG,
Thomas

A.Harrenberg

Hi Thomas
Zitat von: buspirat am 12 Februar 2017, 01:11:17
folgende Idee: Der SendStack weiß ja, daß der auf die nächste WUN warten muss.
Könnte man die Anfrage nach der Nonce ganz oben auf den Stack legen?

Die anderen Befehle sollten natürlich nur abgearbeitet werden, sobald die WUN kommt.
Eventuell kann man hierfür eine Barriere zusätzlich auf den SendStack legen.
Das mit dem nach oben auf den Stack legen habe ich schon gemacht, die, wie du es nennst, "neue Barriere" ist das Problem. Hierzu muss der Ablauf von addToSendStack() und processSendStack() angepasst werden und das Verhalten muss noch flexibler werden.

Ich bin gerade dabei einen neuen Ablauf zu entwickeln und muss denn dann mal mit ein paar Szenarien durchspielen ob auch wirklich der gewünschte Ablauf dabei rauskommt. Das Problem hierbei ist das man kaum alle möglichkeiten mit Re-Transmit, neuen Nachrichten vom Gerät, doppelten Messages etc. im Voraus abschätzen kann. Und genau an sowas scheitert dann so eine Ablaufsteuerung im Allgemeinen dann in der Realität.

Zitat von: buspirat am 12 Februar 2017, 01:11:17
Lustig wird es nur, sobald die Anfrage nach der Nonce und die WUN
halbwegs zeitgleich reinkommen. Dann sollte Dein neuer Code greifen,
daß bis zu xx Nonces kurzzeitig gleichzeitig aktiv seien dürfen.

Lustig wird es auch wenn während einer laufenden Übertragung das Gerät z.B. wegen einer Bewegung eine neue Kommunikation startet. Hier zu erkennen das vom Gerät die laufende Kommunikation abgebrochen wurde und eine neue startet, ist gerade meine Herausforderung... (und natürlich falls möglich die alte Kommunikation danach wieder aufzunehmen...)

Dummerweise spinnt gerade mein HomeMatic Dongle... Daran hängt meine Heizungssteuerung, muss mich also erst mal darum kümmern, da ist der WAF deutlich höher ,-)

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

buspirat

Zitat von: A.Harrenberg am 12 Februar 2017, 09:03:41
Ich bin gerade dabei einen neuen Ablauf zu entwickeln und muss denn dann mal mit ein paar Szenarien durchspielen ob auch wirklich der gewünschte Ablauf dabei rauskommt.
eventuell wäre es möglich, vom bisherigen starren Aufbau einer Liste als "SendStack" wegzugehen:

Man könnte eine Liste von Objekten (=Z-Wave Befehlen) verwalten,
die sich selbst Ihren Zustand merken: SendWhenPossible, WaitForWakup, TransmitRetry, WaitForAck, usw.

Sprich jeder Befehl bekommt eine eigene State-Machine, der ZWave-Stack geht
stets die komplette Liste durch und sucht nach Befehlen die er abarbeiten kann.

Das ganze könnte man dann noch mit Prioritäten versehen, damit Anfragen
nach einer Nonce zuerst und sofort beantwortet werden. Eventuell
genügt es die Anfrage nach einer Nonce stets oben in der Liste einzufügen
und die Priorisierung wegzulassen.

Der zusätzliche Verwaltungsaufwand für das Durchiterieren der Liste
nach bearbeitbaren Befehlen ist gering, da der SendStack normalerweise
eher wenig Befehle enthält. Vorteil ist, daß man sich bei jedem Befehl
zusätzliche Informationen merken kann:

- verwendete Nonce bei SECURITY-Befehlen
- Erstellungsdatem des Befehls für Timeout-Handling pro Befehl
- Anzahl der Retries


Was für ein neuer Aufbau schwebt Dir denn momentan vor?

PS: Viel Glück mit der Heizung ;)

A.Harrenberg

Hi,

also nichts neues, sondern nur weitere "modi" des Stacks wie setsec / getsec, besondere mode für das absezten einer Nonce bei WU-Geräte VOR der WUN. Die Verschlüsselung würde dann aber innerhalb von processSendStack getriggert werden und es müsste gekennzeichnet werden das der Befehl dann bereits verschlüsselt ist. Hierzu wollte ich setenc / getenc als mode/status verwenden. Ich bin aber noch nicht so weit mit "nachdenken" das ich beurteilen kann ob ich nicht die unverschlüsselte Nachricht evtl. auch "aufheben" sollte um sie evtl. erneut mit einer neuen NONCE verschlüsseln zu können falls beim Transmit mal was schief läuft.

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

A.Harrenberg

Hi,

damit ich mich etwas besser im Code orientieren kann und um mir noch mal die ganzen Abläufe vor Augen zu führen habe ich mal ein paar Funktionen in yEd als Flußdiagramm dargestellt. Das ganze ist natürlich nicht vollständig und teilweise stark vereinfacht, die (für mich wichtigen Abfragen und FUnktionen sind aber drin).

ZWave_addToSendStack()
ZWave_processSendStack()
ZWave_Cmd()
ZWave_Parse()

Es gibt auch eine Art Übersicht mit allen 4 Funktionen, da ist dann aber die automatische Anordnung in yEd überfordert und macht recht merkwürdig Sachen mit den Diagrammen...

Ich habe für mich die Symbole teilweise eingefärbt um das "Thema" zu markieren, gelb -> Stack, blau -> WakeUp, orange -> Security.

Erstellt wie gesagt in yEd, V3.16.2.1.

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

buspirat

Zitat von: A.Harrenberg am 12 Februar 2017, 21:35:47
habe ich mal ein paar Funktionen in yEd als Flußdiagramm dargestellt.
das sieht mir recht vollständig aus. Krass wie komplex das jetzt schon ist.
Wieviele Stunden hast Du an den Diagrammen gewerkelt?

Ich bin mir weiterhin nicht sicher, ob es nicht auf lange Sicht einfacher ist, die ganzen Abläufe in eine saubere State-Maschine zu kippen. Das ganze Handling von Wakeup, Security mit seinen Callback-Timern und Co wird sicherlich nicht einfacher, wenn noch S2 Security dazu kommt.

Kurzfristig wäre es natürlich schön das Problem mit der Security-Kommunikation zu beheben und dann vielleicht mal nachdenken, wie man mehr Übersicht in die Abläufe reinbekommt.

Wenn man das ganze besser kapselt, dann könnte man auch Unit-Tests schreiben, die eine Z-Wave Kommunikation simulieren. So bekommen wir besser mit, ob eine Code-Änderung einen anderen Ablauf stört. Der Unit-Test könnte dann auch Paketverlust simulieren.

A.Harrenberg

Hi,
Zitat von: buspirat am 15 Februar 2017, 00:32:05
das sieht mir recht vollständig aus. Krass wie komplex das jetzt schon ist.
Wieviele Stunden hast Du an den Diagrammen gewerkelt?
ja, vor allem die "Übersicht" mit allen Funktionen macht schon was her. Und das sind ja bei weitem nicht alle Funktionen von ZWave (wenn auch die wichtigsten...
Das hat schon ein paar Abende gedauert und 1-2 WE gedauert... Allerdings geht dabei auch immer Zeit drauf mal im Code hin-und-her zu springen um kleinere Funktionen nachzusehen oder es mit anderen Stellen zu vergleichen.

Zitat von: buspirat am 15 Februar 2017, 00:32:05
Ich bin mir weiterhin nicht sicher, ob es nicht auf lange Sicht einfacher ist, die ganzen Abläufe in eine saubere State-Maschine zu kippen. Das ganze Handling von Wakeup, Security mit seinen Callback-Timern und Co wird sicherlich nicht einfacher, wenn noch S2 Security dazu kommt.
Im Prinzip ist es ja bereits eine Statemachine... Der Status ist im Typ des Stackeintrags kodiert und daran hangelt sich processSendStack weiter durch. "Stateänderungen" werden durch die Aufrufparameter von processSendStack initiiert (next/ack/msg/...)

Ich weiß jetzt natürlich nicht was Dir unter einer "sauberen" Statemachine vorschwebt.

S2 wird die Sacher sicherlich NICHT einfacher machen, um das aber jetzt im Stack berücksichtigen zu können müsste man zumindest den Ablauf von S2 JETZT schon verstanden haben und eine Idee zur Implementierung haben.

Zitat von: buspirat am 15 Februar 2017, 00:32:05
Kurzfristig wäre es natürlich schön das Problem mit der Security-Kommunikation zu beheben und dann vielleicht mal nachdenken, wie man mehr Übersicht in die Abläufe reinbekommt.
Das ist jetzt erst mal das Ziel und die Hoffnung wäre das es danach auch einfacher ist es anzupassen.

Zitat von: buspirat am 15 Februar 2017, 00:32:05
Wenn man das ganze besser kapselt, dann könnte man auch Unit-Tests schreiben, die eine Z-Wave Kommunikation simulieren. So bekommen wir besser mit, ob eine Code-Änderung einen anderen Ablauf stört. Der Unit-Test könnte dann auch Paketverlust simulieren.
Puh, sowas zu simulieren übersteigt momentan aber meine Fähigkeiten...

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

tux75at

Hi,

Ich hoffe es ist ok, wenn ich diesen Thread wieder nach oben hole.
Da ich jetzt auch zu diesem Problem gekommen bin und einen Verweis auf diesen Thread gefunden habe, denke ich das es eigentlich richtig ist.

Die Diagramme sind gut gezeichnet, auch wenn man sich da etwas reinknien muss um das zu verstehen. Ohne Unterstützung des Erstellers ist dies vielleicht garnicht möglich. Diese Abläufe sind schon viel zu komplex geworden.

In den Spezifikationen sind einige Abläufe skizziert (bei weitem nicht so genau), aber zu Batteriebetrieben mit wakeup und security ist nichts dabei (zumindest habe ich es "noch" nicht gefunden).

Meine Idee dazu (keine Ahnung ob das Umsetzbar ist oder Gedanken die Ihr auch schon hattet) ....
Bei einem Befehl von FHEM an ein batteriebetriebenes Gerät, weiß der FHEM Server, dass diese Nachricht erst nach einer WUN gesendet werden kann.
Wenn FHEM hingegen etwas empfängt, kann die Antwort sofort gesendet werden.
Aus meiner Sicht benötigt die Kommunikation einen SendStack und einen WUNStack. Nachrichten die an ein batteriebetriebenes Gerät gesendet werden sollen, bei dem Bekannt ist, dass es eine WUN benötigt muss auf den WUNStack. Alles andere was in der Kommunkation erfolgt (ACK etc.) sollte direkt auf den SendStack.
Ich verstehe das Problem dabei, man müsste wissen wo man sich in der Kommunikation befindet. Also wird man wohl nicht daran vorbeikommen eine Statemachine für jeden Befehl zu Bauen, außer es ist anhand der aktuellen Nachricht möglich zu erkennen, dass ein Befehl vorbei ist, um den nächsten vom WUNStack zu holen.

Ich versuche mich in die Kommunikation einzulesen, bin aber bei noch lange nicht soweit Input zu liefern. Die Specification hat schon viel zu viele Seiten.
Wie viel Zeit ich dafür hab, kann ich auch nicht sagen.

Gruß
   Tux

dmq

Hi Tux,

ich denke hier ist es gut aufgehoben. Wenn ich etwas beisteuern kann, melde ich mich oder komm' Du auf mich zu (testen, unterschiedliche Geräte etc.). Vielleicht finden wir ja auch noch ein paar Mitstreiter / Interessenten.

Gruß

dmq