One-Way-Loader - kompakter Krypto-Bootloader für AVR-Mikrocontroller


Dieser Bootloader läuft auf den meisten Mikrocontrollern der Serie TinyAVR und MegaAVR. Anders als alle anderen verwendet er ein konsequentes Einweg-Protokoll und braucht überhaupt keinen Rückkanal. Seine Daten empfängt er über eine existierende RS232-, RS485- oder USB-RS232-Anbindung oder über eine minimalistische und/oder maßgeschneiderte Programmierschnittstelle, die tatsächlich nur einen einzigen Porteingang benutzt. Die Datenübertragung ist technisch robust und kryptografisch abgesichert. Komplette Firmware-Updates für EEPROM und Flash lassen sich in einem verschlüsselten Containerformat zusammenfassen und sind bei der Distribution über unsichere Kanäle gegen Übertragungsfehler, Manipulation und Ausspähung geschützt.


Einleitung | Idee und Konzept | Technische Details | Schnellstart | Anmerkungen | Lizenz | Download | Links | Zurück

OWL web draft cc0
  • Universeller Bootloader für viele ATtinys und ATmegas; Firmware unter 512 Bytes.

  • Robuste Einweg-Übertragung mit RS232-Timing; fortschrittliches Autobauding, minimale Anforderungen an die Interface-Hardware

  • Kryptografie besorgt Datenschutz, Datenintegrität, Authentisierung und einzigartige Geräteadressen.

  • Software-Tool für Bootloader-Generierung, Datenübertragungen, Schlüsselverwaltung.

  • Senden von EEPROM- und Flash-Daten in einem Durchgang; verschlüsseltes Distributionsformat; Unterstützung von Bootloader-Serien.

  • Komplettlösung für Firmware-Sicherheit und gute Laune!


Einleitung

In der Welt der Mikrocontroller stellen sogenannte Bootloader mit RS232-Schnittstelle eine unkomplizierte und preiswerte Alternative zur Programmierung über ISP dar.

Das Thema Sicherheit wird in diesen Tagen immer wichtiger... Schon ein passwortgeschützter Bootloader kann den Zugriff auf einen berechtigten Personenkreis beschränken. Innerhalb des Controllers sind Daten und Programme auch sehr sicher, sobald der ISP-Zugriff per Lockbits gesperrt wurde. Außerhalb des Controllers liegen Firmware-Updates oft in unverschlüsselter Form vor und sind weiterhin den Gefahren von Kompromittierung, Manipulation oder ganz profanen Zufallsfehlern ausgesetzt. Bei rein lokaler Nutzung ist das noch kein Problem. Interessant wird es im Zusammenhang mit Applikationen, die erhöhte Sicherheitsanforderungen stellen und von realen Anwendern im Feld aktualisiert werden sollen. Hier braucht es nicht nur eine idiotensichere Schnittstelle , sondern gegebenenfalls auch echte Verschlüsselung.

Ein Krypto-Bootloader schützt Datenübertragungen auf dem gesamten Transportweg von der Quelle bis zum Zielgerät gegen Ausspähung, Manipulation und Übertragungsfehler. Der Krypto-Bootloader akzeptiert nur verschlüsselte Übertragungen und entschlüsselt die Daten erst unmittelbar vor den Schreibzugriffen im Inneren des Controllers. Firmware-Updates liegen idealerweise nur noch an den "Endpunkten" in unverschlüsselter Form vor; einmal in der geschützten Entwicklungsumgebung des Erstellers und natürlich in einem oder mehreren Ziel-Geräten. Für Krypto-Bootloader kommt meist symmetrische Verschlüsselung zum Einsatz, da diese ressourcensparend umsetzbar ist und klare Zugriffsrechte sicherstellt. Nur, wer den Bootloader-Schlüssel für ein Zielgerät besitzt, kann dort ein Firmware-Update einspielen. Keine Hintertürchen, keine Drittparteien, kein Verfallsdatum. Wenn man es richtig macht, garantiert der Krypto-Bootloader einen umfassenden Firmware-Schutz.

So einfach kann, soll und muss es sein! Nun stellt so eine Bootloader-Firmware bekanntlich spezielle Anforderungen. Die ganze Funktionalität muss äußerst kompakt, unabhängig, zuverlässig und transparent realisiert sein. So etwas lässt sich nicht wirklich an einem Wochenende im Baukastensystem zusammenhämmern. Das ist ein klassischer Einsatzfall für die echte Programmierung in Assembler, dann klappt's auch mit dem transparenten Gesamtkonzept! Man hätte sich ein Beispiel an TinySafeBoot nehmen können... Der hat schon vor Jahren friedlich demonstriert, wie ein einsatzbereiter und ressourcensparender AVR-Bootloader samt plattformübergreifender Software-Unterstützung aussehen kann. Ein praxisbezogenes Feature besteht zum Beispiel darin, dass die Software maßgeschneiderte Bootloader generieren kann, ohne auf eine bestimmte Toolchain angewiesen zu sein.

Das anhaltende Feedback zu TSB scheint zu bestätigen: Viele AVR-Nutzer, die noch selbst denken und entwickeln, wollen unabhängige und transparente Lösungen. Ein vergleichbarer Krypto-Bootloader stand auch auf meiner Wunschliste ganz weit oben... Angesichts der vielen inspirierenden Bootloader-Machwerke, die sich meinem Bewusstsein in letzter Zeit aufgedrängt haben, wurde aus der Wunschliste nun doch wieder eine To-Do-Liste - und schließlich dieses kleine Projekt hier...

Nach oben | Index


Idee und Konzept

Der "One-Way-Loader" verwirklicht und vereint folgende Ideen und Konzepte:
  1. Einweg mit Mehrwert
    In der Regel empfängt so ein Bootloader Daten von einem Computer, um sie in verschiedene Speicherbereiche seines "Wirts-Controllers" zu schreiben. Die umgekehrte Übertragungsrichtung, also Daten lesen , um sie an einen Computer zurückzusenden, beherrscht kaum ein Bootloader, und das Feature wird auch praktisch nie gebraucht. Nicht einmal im Entwicklerumfeld, denn dort steht üblicherweise ISP/JTAG zur Verfügung. Im Übrigen heißt es ja auch Boot loader, und nicht Bootsaver... Wir stellen nüchtern fest: Ein Bootloader für Pragmatiker und Endanwender muss nur Schreibzugriffe beherrschen.
    Die Daten fließen also nur in eine Richtung, nämlich vom Computer zum Controller. Dennoch benötigen die meisten Bootloader eine voll ausgebaute serielle Schnittstelle mit Hin- und Rückkanal. Das ist natürlich den mehr oder weniger angestaubten Protokollen geschuldet, die ständig irgendwelche Bestätigungszeichen oder Prüfsummen zurücksenden wollen.
    Die Abhängigkeit von einer bidirektionalen Schnittstelle schränkt die Einsatzgebiete des Bootloaders empfindlich ein, vor allem dort, wo Portleitungen knapp sind oder wo eigentlich gar keine RS232/RS485-Anbindung vorgesehen war. Manch neuzeitlicher Bootloader kann immerhin "One-Wire". Auf einen Schlag halbiert sich der Bedarf an Portleitungen, aber dafür muss die eine Leitung bidirektional funktionieren und wir brauchen auf der PC-Seite eine spezielle Adapterschaltung (CI-V-Interface).
    Stellt sich doch die Frage: Ist dieses Hin und Her auf zwei Leitungen, oder auf einer bidirektionalen Leitung, wirklich "alternativlos", wie uns die Tellerrandhocker und Protokollfetischisten weismachen wollen?
    Spoiler-Alarm: Die Datenflusssteuerung wird überflüssig, wenn der Sender ein auf den Empfänger zugeschnittenes Timing im Voraus berechnen und einhalten kann. Der Fehlerschutz lässt sich mit einer kryptografischen Über-Alles-Prüfsumme erschlagen!
    So kommen wir zu einem Einweg-Bootloader, der wirklich keinen Rückkanal mehr braucht. Ihm reicht eine einzelne unidirektionale Portleitung, auf der wir bedarfsweise ein serielles Datensignal einspeisen. Mit derart minimalen Hardware-Anforderungen ergeben sich eine Menge interessanter Optionen für ultrasimple und/oder maßgeschneiderte Programmierschnittstellen. Bei alledem bleibt der Einweg-Bootloader direkt kompatibel zu gewöhnlichen RS232- oder RS485-Schaltungen, wo er dann einfach nur den Empfangszweig nutzt. Auf der Softwareseite beim Computer vereinfacht sich die Handhabung der seriellen Schnittstelle noch ein ganzes Stück, sodass hier ohne besondere Klimmzüge ausgesprochen robuste und plattformübergreifenden Lösungen umsetzbar sind. Was zu beweisen war!

  2. Kryptografie sichert Datenschutz, Datenintegrität, Authentisierung und einzigartige Geräteadressen
    Manch einer wird wohl spätestens an dieser Stelle in nervöse Zuckungen verfallen und einwerfen wollen: "Erst diese krasse Einweg-Idee, und jetzt will er auch noch mit KRYPTO rummachen? Das kann doch NIEMALS hinhauen..."
    Und ob das hinhaut! Es funktioniert sogar bedeutend besser, als ohne Krypto. Aber immer der Reihe nach.
    Für Firmware-Datenübertragungen gilt bekanntlich "Null Fehlertoleranz". Die Einweg-Übertragung sollte und kann durchaus robust angelegt sein. Realistischerweise können Fehler selbst unter kontrollierten technischen Bedingungen trotzdem mal vorkommen. Fehlerkorrigierende Codes gibt es, aber die würden das Datenvolumen enorm aufblähen und wären auch kein Garant für absolute Fehlerfreiheit. Ohne Rückkanal kann unser Einweg-Bootloader jedoch kein fehlerhaftes Paket neu anfordern und er kann kein externes Verifying durchführen. Alles Konzepte aus der Mottenkiste der Modem-Übertragungen, die hier fehl am Platze sind.
    Jetzt kommt Kryptografie ins Spiel. Wir nehmen eine beliebige Blockchiffre, wenden eine bestimmte Methode der Schlüsselverkettung an und bauen damit ein Übertragungsformat, das die Schreibdaten nicht nur richtig verschlüsselt, sondern auch eine kryptografische Gesamt-Prüfsumme liefert (vergleichbar einer MAC). Damit kann unser Bootloader zum Ende der Übertragung einseitig und mit allergrößter Sicherheit feststellen, ob alle Daten vollständig und fehlerfrei durchgekommen sind. War die Super-Prüfsumme okay, dann übergibt der Bootloader direkt an die neu geschriebene Applikations-Firmware. Sollte es jedoch zu einem oder mehreren Fehlern gekommen sein, dann müssen wir halt "in den sauren Apfel beißen" (der aber bekanntlich auch der Gesündeste ist...): Der Bootloader wird dann fehlerhafte Daten komplett wieder löschen, und der Nutzer muss eine neue Übertragung versuchen. Das ist im Zusammenhang mit Firmware-Updates ohnehin die einzig gute Praxis!
    Die Verwendung von Krypto bringt neben der Absicherung der Daten vor neugierigen Blicken und der zuverlässigen Erkennung von Übertragungsfehlern noch weitere Vorteile: Starke kryptografische Schlüssel werden nach dem Zufallsprinzip erzeugt. Auf diese Weise bekommt jeder Krypto-Bootloader eine einzigartige Geräteadresse im Sinne einer UUID zugeteilt. Wir müssen uns in einem Multi-Bootloader-Setup nie wieder mit Passwort-Phantasie-Problemen und möglichen Kollisionen herumschlagen.

  3. Kompakte Firmware für die meisten ATtinys und ATmegas (und, wer weiß...)
    Auch dieser Bootloader soll, wie das Vorläuferprojekt, auf möglichst vielen AVR-Chips laufen. Insbesondere war es mir wichtig, weiterhin die "kleinen" Chips zu unterstützen, schon um ein weiteres Zeichen gegen Ressourcenverschwendung zu setzen.
    Mit paralympischen Übungen in "C" kommt man hier nicht weit! Erst die Programmierung in Assembler ermöglicht es, Signalverarbeitung, Ablaufsteuerung und Kryptosystem in hochkompaktem und transparentem Code unterzubringen. Und so braucht dieser One-Way-Loader für seine erstaunliche Funktionalität keine zwei Kilobytes... er braucht nichtmal ein Kilobyte... er kommt mit einem halben Kilobyte aus!

  4. Software-Tool für Bootloader-Generierung, Bootloader-Datenübertragung und Schlüsselverwaltung
    Die PC-Software zum Krypto-Bootloader ist als Kommandozeilentool konzipiert. Das bedeutet minimale Abhängigkeiten und standardisierte Eingabe-Ausgabe-Schnittstellen. Der Aufruf lässt sich plattformunabhängig in diverse Entwicklungs- und Editorumgebungen sowie in Skript-Abläufe einbinden. Selbstverständlich wird die Software als ausführbare Datei für Linux- und Windows-Konsole zur Verfügung stehen.
    Die Software muss verschlüsselte Firmware-Updates an "autorisierte Zielgeräte" (also solche, für die wir selbst den Schlüssel besitzen) senden können. Das Ganze soll nicht mehr Umstände machen, als der Zugriff auf einen unverschlüsselten Bootloader. Niemand merkt sich Bootloader-Passwörter. Der benutzerfreundliche Kompromiss besteht darin, jedem Zielgerät einen eindeutigen und memorierbaren Klarnamen zuzuordnen. Die Software holt sich den dazu passen Krypto-Schlüssel und alle weiteren Infos aus einer lokalen Datenbank.
    Die Software soll auch wieder maßgeschneiderte Bootloader "out of the box" erzeugen. Eine nützliche und rationale Option, kein Muss. Wer will, kann auch aus dem offengelegten Assemblerquelltext in der Arbeitsumgebung seiner Wahl einen Bootloader zaubern; und sei es nur zur Vergewisserung, dass der selbst assemblierte Code mit dem von der Software erzeugten Code identisch ist.
    Ein weiteres Feature, das in den Beschäftigungstherapien für Nerds nicht einmal angedacht wird, gehört beim One-Way-Loader zum Standardumfang: Die halbautomatische Erzeugung einer ganzen Bootloader-Serie mit individuellen Schlüsseln und Seriennummern, und dazu passend die Generierung von Firmware-Updates für eine solche Bootloader-Serie. Könnte ja sein, dass mal jemand auf die total verrückte Idee kommt, und mehr als nur nur zwei oder drei Geräte mit Krypto-Bootloadern versorgen will...

  5. Cooler Name, coole Lizenz
    Nach einigem Hin und Her habe ich mich entschlossen, den Einweg-Bootloader nach seinem Alleinstellungsmerkmal, der Einweg-Übertragung, zu benennen. Also heißt das Teil jetzt "One-Way-Loader", "OneWayLoader" oder "OWL". (Wer Eulen nicht mag, hat halt Pech gehabt...)
    Der One-Way-Loader ist quelloffen. Das ist alternativlos, da sich hier alles um Sicherheit und Krypto dreht.
    Der One-Way-Loader steht unter MIT-Lizenz.
    Das hat vor allem pragmatische Gründe. Meine Zeit ist kostbar und ich habe Wichtigeres zu tun, als über seitenlange Lizenzbedingungen zu diskutieren. Die freizügige und unkomplizierte MIT-Lizenz ist eine Sicherheitsgarantie für alle Beteiligten und ermöglicht eine freiwillige und faire Zusammenarbeit.

Wer's ganz genau wissen will, sollte sich die Technischen Details reinziehen. Nur für Hardcore-Fans!


Direkt ausprobieren: Schnellstartanleitung


Tipp: Für invertierte Bildschirmdarstellung steht (seit 'ner halben Ewigkeit) ein alternativer CSS-Style zur Verfügung. Unter Firefox mal Ansicht - Webseitenstil - Schwarz auf Weiß ausprobieren!


Serviervorschläge:
  • Ultimativer Ersatz für TSB, da dieselbe Hardwarebasis unterstützt wird
  • Transparenter Krypto-Schutz für lokale Projekte
  • Firmware-Updates "im Feld" über besonders simple und/oder robuste Schnittstellen
  • Gesicherter Update-Kanal für Nur-EEPROM- oder Nur-Flash-Daten
  • Nutzung existierender RS232/RS422/RS485-Schnittstellen
  • Nutzung minimalistischer und versteckter Programmierschnittstellen, z.B. LED + Photodiode
  • Distribution kompletter Firmware-Updates über öffentliche Kanäle (Web, FTP, E-Mail)
  • Firmware-Schutz für besondere Anwendungen



Nach oben | Index


Technische Details


  1. Timing-Trick
  2. Synchro-Autobauding

  3. Logisches Format

  4. Kryptografie

  5. Firmware

  6. Software

  7. Hardware-Optionen




      OWL-Transmission (1) - Timing-Trick

      Problem: Der Bootloader auf einem Mikrocontroller kann normalerweise keinen ununterbrochenen Datenstrom verarbeiten. Er muss seine Schreibdaten in kleinen mundgerechten Häppchen serviert bekommen, die er problemlos zwischenspeichern, bündeln und dann in die verschiedenen Speicherbereiche schreiben kann. Wenn die Daten noch anspruchsvoll entschlüsselt werden müssen, dann braucht dieser Verarbeitungsschritt schon eine nennenswerte Rechenzeit. Der eigentliche Knackpunkt sind aber die physischen Schreibzugriffe in EEPROM oder Flash. In dieser kritischen Phase muss eine Bootloader-Firmware normalerweise den laufenden Schreibzugriff abwarten, oder der Prozessorkern wird sogar komplett angehalten. Das bedeutet, ein interrupt-optimierter Datenempfang würde in der Bootloader-Anwendung nicht viel bringen, außer zusätzlichem Aufwand und Stabilitätsrisiken. Zwischen den Datenblöcken entsteht  immer eine Zwangspause (wir nennen sie mal reißerisch "Totzeit" ), in der unser Controller gar nichts mehr mitbekommt.

      Der Datenfluss muss also zeitlich koordiniert werden.
      In einem einfachstmöglichen bidirektionalen Protokoll sendet der Computer einen Datenblock festgelegter Größe und wartet dann, bis der Controller irgendwann zurückmeldet, dass er wieder empfangsbereit sei. Vorher darf der Computer keine neuen Daten oder Kommandos senden. Dieses Hin und Her auf zwei Leitungen (oder auf einer bidirektionalen Leitung) wollen wir abschaffen. Und so geht's:

      Lösung: Es ist möglich, die Totzeiten des Controllers im Voraus zu berechnen , wenn einige Rahmenbedingungen bekannt sind. Dann weiß der Computer ganz genau, wie lange der Controller zur Verarbeitung der aktuellen Daten brauchen wird. Der Computer muss also "nur noch" eine zeitlich exakte Übertragung hinbekommen. Gibt's aber schon das nächste Problem: In einer modernen RS232-Implementierung lassen sich definierte Sendepausen praktisch nicht mehr umsetzen. Was aber immer funktioniert, ist das Senden von seriellen Stopf- oder Füllzeichen. Diese garantieren zeitliche Mindestabstände zwischen den Nutzdatenblöcken . Sind die Schutzintervalle großzügig berechnet, dann bekommt der Bootloader immer genügend Zeit, um die aktuellen Daten zu verarbeiten. Kurz nachdem der Bootloader wieder auf Empfang geht, kommt auch schon das nächste Datenpaket.
      Das OWL-Signal ist eine einseitige RS232-Übertragung im Modus 8-N-1 in der gegebenen Baudrate.
      Das OWL-Signal lässt sich über jede normgerechte RS232-Schnittstelle senden.
      • Es überträgt nur in eine Richtung, nämlich vom Computer ( "Sender") zum Controller ("Empfänger").
      • Es sendet verschlüsselte Datenblöcke, um Vertraulichkeit und Datenintegrität sicherzustellen.
      • Es berücksichtigt die Totzeiten des Empfängers, indem es zwischen den Blöcken eine vorausberechnete Anzahl von Füllzeichen einfügt.
      • Diese Füllzeichen ("Präambel") garantieren zeitliche Mindestabstände zwischen den Datenblöcken.
      • Die Präambeln ermöglichen dem Empfänger schnelle Neusynchronisation und präzises Autobauding.
      • Die Einweg-Übertragung ("Transmission") funktioniert ohne Flusssteuerung und benötigt keinen Rückkanal.
      • Die Einweg-Übertragung stellt minimale Anforderungen an RS232-Hardware und Software.
      • Das unterbrechungsfrei gesendete Signal wird technisch besonders robust.

      Zeitverlauf einer OWL-Transmission für ATtiny25 mit 10 MHz (4 Blöcke EEPROM, 8 Blöcke Flash bei 9600 Baud)
      Allgemeines: Das obenstehende Diagramm wurde vom Mitschnitt einer realen "OWL-Transmission" abgeleitet. Es handelt sich um einen durchgehenden Sendedatentrom. Die verschiedenen Datentypen sind grafisch hervorgehoben. Wir sehen auf einen Blick, dass die Strecken mit Füllzeichen (PREAMBLE) ziemlich unterschiedliche Längen haben. In einer bidirektionalen Übertragung wären das Sendepausen, und es würde sich ein ganz ähnliches Bild ergeben. Die Präambeln berücksichtigen die Verarbeitungs- und Totzeiten des Ziel-Controllers je nach momentanem Betriebszustand und sind individuell zu berechnen.

      Block-Sendedauer: Der einzelne Datenblock besteht immer aus 16 Bytes plus Startzeichen. Die Sendedauer eines Datenblocks ist bei gegebener Baudrate immer gleich. Bei 9600 Baud dauert jeder Block knapp 18 Millisekunden ( tB).

      Einleitende Präambel (INTRO PREAMBLE): Zum Beginn der Bootloader-Sitzung muss sich der Empfänger erstmalig auf das ankommende (oder bereits laufende) Sendesignal einstellen. Die INTRO PREAMBLE ist in dieser Darstellung recht kurz geraten, kann aber beliebig verlängert werden. Das ist zum Beispiel hilfreich, wenn Controller-Reset und Sendebeginn manuell koordiniert werden müssen.

      Block-Entschlüsselungsdauer
      : Die Entschlüsselung eines Datenblocks kostet Rechenzeit. Bei Taktfrequenzen im MHz-Bereich liegt die "decryption time" ( tD) bei wenigen Millisekunden. Jeder Block muss entschlüsselt werden. Deshalb fließt die Block-Entschlüsselungsdauer in alle Präambel-Berechnungen mit ein und gibt somit die Mindestdauer der Präambeln vor. Sicherheitshalber legt man aber noch ein paar Zeichen "obendrauf", um Laufzeitabweichungen auszugleichen und um dem Empfänger eine sichere Nachsynchronisation zu ermöglichen. Die physischen Schreibzugriffe in EEPROM und Flash brauchen zum Teil noch viel länger, wie wir sehen.

      Authentisierungs-Sequenz (S1): Die ersten drei aufeinanderfolgenden Blöcke dienen der Authentisierung des Senders gegenüber dem Empfänger, also der "Anmeldung" beim Bootloader. Dieser Schritt spielt sich ausschließlich im Arbeitsspeicher des Controllers ab und ist nicht sehr rechenintensiv, daher reichen die Basis-Präambeln mit der Mindestlänge ( tD) aus.

      EEPROM-Sequenz (S2): EEPROM-Speicher kann direkt überschrieben werden, braucht aber pro Byte schon mehrere Millisekunden, sodass sich die Schreibzeit für einen Block aus 16 EEPROM-Adressen auf satte 60 Millisekunden ( tEW) summiert. Da müssen wir durch, aber nur, wenn tatsächlich EEPROM-Daten geschrieben werden. Die längeren Präambeln nach jedem EEPROM-Datenblock sind deutlich zu erkennen.

      Flash-Sequenz (S3): Nach dem ersten Flash-Datenblock sehen wir im Diagramm eine auffällig lange Pause von ca. 180 ms ( tFE). In dieser Zeit löscht der Bootloader den Applikations-Flash, bevor neue Daten geschrieben werden können. Danach geht es aber zügig voran. Dem aufmerksamen Auge wird nicht entgangen sein, dass die Länge der Präambeln zwischen den Flash-Datenblöcken leicht unterschiedlich ist. Das hängt mit der Speicherorganisation im Flash zusammen. Im Ziel-Chip (hier ATtiny25), ist der Flash-Memory in Pages (Speicherseiten) von je 32 Bytes unterteilt. Der Datenblock hat aber immer genau 16 Bytes. Also muss das Bootloader-Programm die Daten von zwei Blöcken zusammenfassen, bevor es eine Flash-Page schreiben kann. Dementsprechend muss der Sender auch nur nach jedem zweiten Block die verlängerte Präambel ( tFW) in den Datenstrom einfügen.
      (Anmerkung: Auf Controllern mit größerem Flash ist gewöhnlich auch die Pagesize größer. Dann findet der Flash-Write nur noch alle 4, 8 oder 16 Blöcke statt, und es ergibt sich beim Löschen und beim Programmieren des Flash ein deutlicher Optimierungseffekt.)

      Zu den Berechnungen: Um das maßgeschneiderte Timing zu erzeugen, braucht der Sender ein Vorwissen über den Empfänger. Neben dem passenden Krypto-Schlüssel muss der Sender vor allem den Controller-Typ, die Anzahl Prozessortakte zur Block-Entschlüsselung und die absolute Taktfrequenz des Ziel-Controllers kennen. Wie diese Informationen verwaltet und verarbeitet werden, steht unter Software.
      Hörbeispiel:  OWL-Transmission mit 1 kB Nutzdaten bei 9600 Baud als Audiodatei

      Nach oben | Index




      OWL-Transmission (2) - Synchronisation und Autobauding

      Der Sender fügt zwischen den Datenblöcken eine genau berechnete Anzahl von Präambel-Zeichen ein und erzeugt damit garantierte Schutzintervalle, die dem Empfänger stets genügend Zeit zur Verarbeitung der bisherigen Daten verschaffen.
      In dem Moment, wo sich der Empfänger wieder auf die Leitung schaltet, trifft er auf die letzten Zeichen der auslaufenden Präambel. Diese ermöglichen ihm eine schnelle Neusynchronisation auf den seriellen Zeichenrahmen und einen präzisen Abgleich auf die serielle Geschwindigkeit (Autobauding).

      Auswertung der OWL-Präambel vor dem Wiedereinstieg in die Datenübertragung
      Festlegungen:
      • Das Präambel-Zeichen ($CC, &b11001100) ermöglicht Synchronisation und Autobauding.
      • Das Blockstart-Zeichen ($55, &b01010101) markiert Ende der Präambel und Beginn des Datenblocks.

      Vor-Synchronisation:

      • Der Empfänger kann auf einen Leerlaufzustand treffen oder asynchron in eine laufende Übertragung stoßen. Er kann folgende Signalzustände vorfinden:
        • Ein Low-Pegel, also Startbit oder 0-Bitzelle, wird immer abgewartet, bis wieder High anliegt.
        • Ein High-Pegel, also Leerlauf, Stoppbit oder 1-Bitzelle , wird abgewartet, bis die Leitung auf Low geht.
        • Der Beginn dieser Low-Phase ist der exakte Startzeitpunkt für die erste Messung.

      Synchro-Autobaud-Messung:

      • Das Präambel-Zeichen enthält zwei durchgängige Low-Phasen von 3 und 2 Bitzellen Dauer.
      • Der Empfänger misst die Dauer von zwei aufeinander folgenden Low-Phasen.
      • Das Ergebnis der zweiten Messung wird vom Ergebnis der ersten Messung abgezogen:
        • Positives Ergebnis ( 3 - 2 = 1 ) bedeutet, dass die Low-Phasen innerhalb des Zeichenrahmens erfasst wurden. Der Empfänger ist mit dem Zeichenrahmen synchron und das Messergebnis ist auch schon der gesuchte Timing-Referenzwert.
        • Negatives Ergebnis ( 2 - 3 = -1 ) bedeutet, dass zwei Low-Phasen aus getrennten Zeichen erfasst wurden. Der Empfänger ist noch nicht vollständig synchron. Er überspringt den nächsten High-Low-Wechsel und startet eine neue Doppelmessung, die dann im synchronen Zustand das richtige positive Ergebnis liefern wird.
      • Die Differenzbildung liefert einen fehlerkompensierten Messwert über das Timing einer Bitzelle.

      Datenempfang:
      • Nach der Synchro-Autobaud-Prozedur erfolgt der weitere Zeichenempfang per Software-Decoder.
      • Der Empfänger ...
        • verwirft weitere Präambel-Zeichen, bis das Blockstart-Zeichen eintrifft;
        • decodiert und puffert die nach dem Blockstarter folgenden 16 Datenbytes;
        • entschlüsselt und verarbeitet die Daten im Puffer.
      • Währenddessen beginnt der Sender schon einmal mit der Übertragung der nächsten Präambel.
      • Sobald der Empfänger wieder empfangsbereit ist, findet er die laufende Präambel vor und startet eine Neusynchronisation und erneutes Autobauding. Der Kreis schließt sich.

      Anmerkungen:

      • Allgemein profitieren wir von den Hauptvorteilen eines Software-UAR(T) mit Autobauding: Es können beliebige Portleitungen und verschiedene Baudraten für den Zeichenempfang benutzt werden.
      • Das ausgearbeitete Verfahren ist vergleichsweise flexibel. Es kann vor und während der Übertragung bis zum Timeout auf ein Signal warten oder sich in eine bereits laufende Präambel "einklinken". Letzeres ist während der Übertragung sogar der Normalfall. Fehlsynchronisation oder Mehrdeutigkeiten praktisch nie auf.
      • Das Verfahren wertet nur die aktiven Low-Zustände auf der Datenleitung aus. Eine "stotternde" Übertragung (Leerlauf des Sendepuffers) beeinflusst die Messgenauigkeit überhaupt nicht.
      • Das Verfahren ist ausgeprochen robust. Die differenzielle Messung gleicht Asymmetrien in den Signalflanken aus. Damit lassen sich auch verzerrte Signale bis zu einem gewissen Grad noch auswerten.
      • Präambeln, Blockstarter und Datenblöcke sind als Datenstrom digital ausgeglichen. Bei kontinuierlicher Sendung entsteht ein perfekt ausbalanciertes serielles Signal. Diese bewusst "angezüchtete" Eigenschaft begünstigt gleichspannungsfreie und/oder differenzielle Übertragungsarten und verbessert ganz allgemein die Störsicherheit auf realen Kanälen.
      • Neusynchronisation und Autobauding vor jedem einzelnen Datenblock. Damit ist auch bei sehr langen Durchgängen unter schwankenden oder driftenden Taktfrequenzen ein stabiler Betrieb möglich.
      • Breites Baudraten-Fenster. Die gegenwärtige Assembler-Programmierung nutzt den Wertebereich der verwendeten 16-Bit-Zähler gut aus, sodass sich ein breiter Arbeitsbereich ergibt. ( Tabelle)
      • Synchronisation und Autobauding benötigen nur zwischen 1 und 2,5  Präambel-Zeichen. Die Präambeln können bei eng tolerierten Taktfrequenzen durchaus knapp bemessen werden. Wir bekommen eine zeitoptimierte Übertragung, die bei gleicher Baudrate schneller durchläuft, als eine bidirektionale Bootloader-Sitzung mit einem optimiertem Minimalprotokoll. Grund: Bei der unidirektionalen OWL-Transmission entstehen auf Host-Seite keine weiteren Verzögerungen durch die Richtungsumschaltung und Handhabung von Empfangspuffern.
      Hinweis: RS232-Signalverläufe sind hier als Logiksignale mit unipolaren Pegeln in Normallage dargestellt, wie sie von der U(S)ART-Komponente des Mikrocontrollers erwartet werden und üblicherweise an TTL-kompatiblen Ausgängen eines MAX232 oder FT232 vorliegen. Hier ist die logische "1" (Stoppbit oder Leerlauf) durch einen High-Pegel (meist 3,3 oder 5 Volt) definiert, eine logische "0" entspricht dem Low-Pegel (0 Volt). Darüber hinaus kann die OWL-Firmware auch für Empfangssignale in Inverslage mit umgedrehten Logikpegeln konfiguriert werden, dies bringt in einigen Fällen weitere Hardware-Vereinfachungen.

      Performance

      Nachstehende Tabelle gibt einen Überblick, was mit dem beschriebenen Synchro-Autobaud-Verfahren machbar ist. In einem realen Testaufbau mit ATtiny2313-20PU an 5V mit dem klassischen MAX232-Pegelwandler habe ich Reihenversuche bei verschiedenen Controller-Taktraten durchgeführt. Die Test-Transmission enthielt jeweils ein Datenmuster von 2 x 64 Bytes für den vollen EEPROM und ein einfaches LED-Blinkprogramm für den Flash, das mit ca. 1 kB an Zufallsdaten aufgefüllt war.
      Der Chip wurde vor jedem neuen Versuch über ISP komplett gelöscht. Damit waren "falsch positive" Ergebnisse ausgeschlossen.

      Auswertung: Wenn die LED unmittelbar nach Abschluss der Transmission fröhlich zu blinken anfing, dann muss logischerweise die gesamte Transmission vollständig und fehlerfrei durchgelaufen sein. In allen anderen Fällen wurde der Versuch als gescheitert abgehakt. In einigen Zweifelsfällen wurden Speicherinhalte nochmals per ISP ausgelesen und geprüft. Dabei bestätigte sich, dass die Fehlerbehandlung durch die aktuelle Bootloader-Firmware sehr verlässlich funktioniert. (Siehe OWL-Signal - Logisches Format.)

      Baudraten-Fenster bei verschiedenen Prozessor-Taktraten

      MCU-Takt (kHz)
      Baud Min. Baud Max.
      16
      < 30
      100
      128
      30
      450
      500
      50
      900
      1000
      100
      1800
      2000
      200
      3600
      3000
      300
      4800
      3560
      450
      7200
      4000
      450
      7200
      4433
      450
      9600
      6000
      450
      14400
      8000
      600
      14400
      10000
      600
      19200
      12000
      1200
      28800
      14745
      1800
      38400
      16000
      2400
      38400
      17734
      2400
      57600
      24000
      3600
      76800
      27256
      4800
      115200
      30000
      9600
      115200

      Anmerkungen:
      1. Die Tabelle ist nicht auf TSB oder ähnliche Bootloader übertragbar. OWL hat einen viel breiteren Arbeitsbereich!
      2. Faustformel für das Baudraten-Fenster in der Benutzersoftware: CLOCK/10 < BAUDRATE < CLOCK*2
      3. Liefert das Interface unsaubere (weniger steile) Pegel, kann es mit der höchsten Baudrate Probleme geben. Die nächstniedrigere Norm-Baudrate sollte dann funktionieren.
      4. Die Untergrenze (Minimum-Baudrate) ergibt sich aus der Tatsache, dass der AVR zur Pulsbreitenmessung einen 16-Bit-Zähler benutzt; dessen Wertebereich wird bei zu langsamem Signal überschritten.
      5. Die Obergrenze (Maximum-Baudrate) ergibt sich aus der zunehmenden Mess-Ungenauigkeit, wenn das serielle Signal im Verhältnis zum Prozessortakt schon relativ schnell ist.
      6. Taktfrequenzen über 24 MHz wurden von einem externen Quarzgenerator eingespeist, da keine spezielle Beschaltung für Obertonquarze vorgesehen war und der ATTiny2313-20PU "eigentlich" nur bis 20 MHz spezifiziert war. Uneigentlich lief dieses Exemplar noch bis über 32 MHz (!) scheinbar problemlos, was die Kernfunktionalität der MCU anging. (Overclocking-Experimente mit Mikrocontrollern - ein interessanter und nicht ganz so kostspieliger Zeitvertreib...)
      7. Im Test wurden nur Norm-Baudraten verwendet. An einem USB-COM-Wandler (z.B. FT232) sind auch nicht-standardkonforme Baudraten, wie etwa 64.000 Baud, einstellbar. Für's Autobauding kein Problem!

      Nach oben | Index



      OWL-Transmission (3) - Logisches Format

      Die Präambeln realisieren auf der Transportschicht ein maßgeschneidertes Timing, das den Rückkanal zur Datenflusssteuerung überflüssig macht und dem Empfänger immer wieder ein Referenzsignal für Synchronisation und Autobauding liefert.

      Für das logische Format einer OWL-Transmission spielt diese Technik keine Rolle. Auf der höherliegenden Kryptoschicht wird nur mit den Datenblöcken zu 16 Bytes gearbeitet.

      Alle Blöcke sind mit RST verschlüsselt. Eine sogenannte RST-Sequenz besteht immer aus einem Initialisierungsvektor (IV), dem eigentlichen Nachrichteninhalt (in einem oder mehreren Blöcken), sowie einem abschließenden Block (VI), der mit dem IV identisch ist. Die Blöcke sind aufgrund des Key-Feedback kryptografisch voneinander abhängig und der rechtmäßige Empfänger kann über den IV-VI-Vergleich eindeutig feststellen, ob die bisherigen Daten komplett und korrekt übertragen wurden. Der OWL-Bootloader nutzt diese Eigenschaft schamlos aus...

      Die OWL-Transmission macht es gleich dreimal hintereinander. Die drei RST-Sequenzen enthalten, immer in derselben Reihenfolge, Daten zur Authentisierung, für den EEPROM und für den Flash. Im Rahmen einer OWL-Transmission wird der Schlüsselgenerator gar nicht wieder zurückgesetzt. Somit sind nicht nur die Blöcke untereinander, sondern auch die Sequenzen kryptografisch aneinander gekoppelt. Im Normalfall erkennt der Empfänger den Abschluss einer fehlerfreien Sequenz und schaltet dann zur nächsten Sequenz weiter. Im Fehlerfall verbleibt der Empfänger in der gegenwärtigen Sequenz und kann (muss) am Ende der Transmission Maßnahmen zur Schadensbegrenzung treffen. Eine weitergehende Differenzierung ist für den Einweg-Bootloader nicht nötig!

      Ablauf der OWL-Transmission (siehe auch Übersichtsdiagramm ):
      • S1: Authentisierung
        • IV = Zufallsdaten, modifizieren Originalschlüssel für alle nachfolgenden Runden
        • Kein Datenblock = Blockade
        • Genau ein Datenblock = Wird verworfen, nur Key-Feedback
        • VI nicht erkannt = Blockade ohne Timeout!
        • VI erkannt = Weiter mit S2
      • S2: EEPROM-Daten
        • IV = Zufallsdaten; modifiziert PRNG-State nach S1
        • Kein Block, direkt VI = weiter mit S3
        • Datenblöcke = in EEPROM schreiben
        • VI nicht erkannt / Timeout = Fehler, bleibe in S2, Blockade
        • VI erkannt = weiter mit S3

      • S3: Flash-Daten
        • IV = Zufallsdaten; modifiziert PRNG-State nach S2
        • Kein Block, direkt VI = Fertig!
        • Mindestens ein Datenblock = Flash-Erase, Zusammenfassung mit weiteren Blöcken, dann Page-Write
        • VI nicht erkannt / Timeout = Fehler, Flash-Erase!
        • VI erkannt = Erfolg, gesamte Übertragung fehlerfrei, Applikation starten!

      Normalfall: Der Sender verwendet exakt denselben Schlüssel, wie der Empfänger und die Übertragung kommt von Anfang bis Ende störungsfrei durch. Der Empfänger kann jeden einzelnen Block korrekt entschlüsseln, erkennt die VIs der jeweiligen Sequenzen und erkennt auch den abschließenden VI von S3. In diesem Moment ist klar, dass alle vorherigen Daten vollständig und fehlerfrei gewesen sein müssen. Die Sitzung war im Ganzen erfolgreich und die Bootloader-Firmware übergibt die Kontrolle an eine bestehende oder neu geschriebene Applikations-Firmware.
      Indirekte Rückmeldung: Sofortiger Start der Applikation.


      Ausnahmefälle:Übertragungsfehler; Unterbrechungen, zu lange Sendepausen (Timeout); Synchronverlust; versehentliche Anwendung eines falschen Schlüssels; absichtliche Anwendung eines falschen Schlüssels (zur Adressierung mehrerer Empfänger auf derselben Leitung); plumpe Manipulationsversuche. Alle diese Situationen erkennt der Empfänger als FEHLER. Je nachdem, in welcher Sequenz er sich gerade befindet, trifft der Empfänger Gegenmaßnahmen.
      Indirekte Rückmeldung: Blockade bis zum Hardware-Reset.


      Weitere Überlegungen: Die OWL-Transmission kommt ohne Steuerzeichen und Kommandos aus. Es werden keine Header-Blöcke oder sonstige Metadaten übertragen, die einen Known-Plaintext-Angriff begünstigen würden. Im Gegenteil, das Chiffrat bekommt mit jedem neuen IV zusätzliche Entropie verpasst.
      Obwohl es sich hier um einen festgelegten Ablauf handelt, sind Schreibzugriffe in EEPROM oder Flash optional. Es ist möglich, nur in den EEPROM oder nur in den Flash zu schreiben, ohne jeweils den anderen Speicherbereich zu berühren. Es ist ebenso möglich, ein komplettes Firmware-Update, bestehend aus Daten für EEPROM und Flash, in einer und derselben Transmission bzw. in einer Transmissions-Datei unterzubringen.

      Nach oben | Index


      Kryptografie

      Der OWL nutzt eine Blockchiffre mit der Bezeichnung "RST" (Randomized Substitution-Transposition). Dabei handelte es sich um ein Studienprojekt zum Thema Blockverschlüsselung. Dieses Kryptosystem definiert eine kombinatorisch simple Blockchiffre, einen bestimmten Key-Feedback-Modus und ein bevorzugtes Dateiformat. Es ist auf praktische Anwendungen ausgelegt, nicht auf akademische Anerkennung und mathematische Eleganz.
      Auf der PC-Plattform gibt es genügend Krypto-Alternativen, die dem weit verbreiteten Glauben an "Zertifiziertes" huldigen und ganz objektiv beim Datendurchsatz besser abschneiden, als mein kleines modular aufgebautes System hier. In der Bootloader-Anwendung sind die Prioritäten etwas anders gelagert. Im Vergleich mit anderen Kandidaten für eine Bootloader-Chiffre stellte sich heraus, dass RST den vielleicht besten Kompromiss aus Codeeffizienz und Sicherheit zu bieten hat.

      Funktionsweise von RST

      Das Verfahren nutzt für seine "randomisierten Substitutionen und Transpositionen" einfache Standardoperationen, wie Addition, Bitshifting, Invertierung und Vertauschung, auf auch etablierte Blockchiffren beruhen. Die Rechenschritte innerhalb einer Blockrunde werden jedoch nicht über feststehende Schlüssel oder Tabellen gesteuert, sondern durch einen fortlaufenden Pseudozufallsgenerator, der zu Beginn der Ver- oder Entschlüsselung mit dem geheimen Schlüssel als Startzahl (seed) geladen wird.
      Der PRNG ist wortwörtlich "Schlüsselkomponente" des Kryptosystems. Er ist im Prinzip austauschbar und kann nach unterschiedlichen Qualitätskriterien realisiert werden, sodass sich je nach Anwendung ein günstiger Kompromiss aus Rundenzahl, PRNG-Stärke und Codebedarf (Mikrocontroller-Anwendungen) finden lässt.
      Der Block-Algorithmus von RST erzielt schon bei Mindestrundenzahl einen mittleren bis guten Avalanche-Effekt. Das bedeutet, ein einziges "gekipptes" Bit im Chiffrat wirkt sich nach der Entschlüsselung auf 10 bis 50 Prozent im wiederhergestellten Klartextblock aus. Nach jeder vollständigen Blockrunde wird jedoch der innere Zustand des PRNG mit dem Klartext des vorherigen Blockes modifiziert. Daraus resultiert eine massive Fehlerfortpflanzung, welche den äußerst wirksamen Authentisierungs- und Fehlererkennungsmechanismus ermöglicht.



      Klartext-Schlüssel-Rückkopplung in RST

      RST-Dateiformat

      Für PC-Anwendungen entstand ein logisches Format zur authentisierbaren und kryptografisch abgesicherten Übertragung von Dateien. Hierbei besteht das Kryptogramm ausschließlich aus verschlüsselten Blöcken und kommt ohne irgendwelche Header-Blöcke aus. Eine solche RST-Sequenz gliedert sich in drei Abschnitte:
      • IV = Block mit verschlüsseltem (geheimem) Initialisierungsvektor
      • DATA = Block oder Blöcke mit verschlüsselter Nachricht (Nutzdaten)
      • VI = Block mit Wiederholung des verschlüsselten IV (Nachricht-Ende-Signatur, MAC-Prüfsumme)
      Der erste Block ist der einzige Block, der mit dem Originalschlüssel verschlüsselt wird. Dieser erste Block ist mit Zufallszahlen aufgefüllt. Infolge der Rückkopplung auf den PRNG wird der erste darauf folgende Nachrichtenblock bereits mit einem komplett neuen und einmaligen Schlüsselsatz bearbeitet. Der erste Block hat also die Funktion eines Initialisierungsvektors oder IV. Damit sind triviale Angriffe auf das Kryptosystem (insbesondere "known plaintext") bereits ziemlich sicher ausgeschlossen, da es, vereinfacht gesagt, für verschlüsselte Zufallszahlen keine kryptoanalytische "Abkürzung" gibt.
      Der IV-Block hat aber noch eine weitere Funktion. Sein Muster aus Zufallszahlen wird mit allergrößter Wahrscheinlichkeit im nachfolgenden Nachrichtenblock nicht noch einmal vorkommen. Das bedeutet, der IV kann als eindeutige Markierung für das Nachrichten-Ende benutzt werden. Zur funktionalen Unterscheidung wird diese abschließende Wiederholung des IV-Blockes "VI" genannt. Der rechtmäßige Empfänger muss zu Beginn der Entschlüsselung nur den Inhalt des ersten entschlüsselten Blocks als VI zwischenspeichern. Im weiteren Verlauf vergleicht er jeden danach entschlüsselten Block mit diesem VI-Muster:
      • Wenn sich ein entschlüsselter Block vom VI unterscheidet, geht der Empfänger davon aus, dass dies ein gewöhnlicher Datenblock ist, der weiterverarbeitet (z.B. abgespeichert) werden kann. Ob diese Daten auch fehlerfrei sind, kann der Empfänger zu diesem Zeitpunkt allerdings noch nicht wissen.
      • Erkennt der Empfänger einen Block, der exakt mit dem VI übereinstimmt, dann weiß er mit größter Sicherheit, dass die vorherige Übertragung authentisch, vollständig und fehlerfrei war.
      • In allen anderen Fällen wird das Ende der Datei erreicht, ohne dass der Empfänger den VI erkennt. (Fehler!)
      Anstelle von Fehler-Lokalisation und Fehler-Korrektur tritt eine zuverlässige Fehlererkennung. (Fehlerhaft entschlüsselte Krypto-Dateien sind normalerweise vollkommen unbrauchbar, und es ist Zeitverschwendung, sich mit fehlerkorrigierenden Maßnahmen auf Dateiebene zu befassen, wenn die Alternative einfach darin besteht, den Download noch einmal zu wiederholen oder die E-Mail noch einmal zu senden.) Der berechtigte Empfänger kann auf Grundlage des IV-VI-Mechanismus in einem Durchgang und mit geringem Aufwand die Authentizität, Vollständigkeit und Fehlerfreiheit einer Nachricht sicherstellen. Diese Funktionalität reicht in vielen Anwendungsbereichen bereits vollkommen aus.

      "OWL-RST"

      Für den One-Way-Loader kommt eine modifizierte 128-Bit-Variante von RST zum Einsatz. Block- und Schlüsselweite sind beim One-Way-Loader auf 128 Bits (16 Bytes) festgelegt.

      Das OWL-Kryptogramm besteht immer aus drei aneinandergereihten RST-Sequenzen . Diese Sequenzen sind wie die einzelnen Blöcke kryptografisch voneinander abhängig, da der PRNG im Laufe der Bootloader-Sitzung nicht mehr zurückgesetzt wird. Somit liefert der letzte VI eine Über-Alles-Prüfsumme zur Gesamtübertragung. Die Fähigkeit, einen Fehler in der Gesamtübertragung sicher zu erkennen, ist das entscheidende Feature für den Einweg-Bootloader.

      Als PRNG für den Bootloader kommt die Software-Umsetzung eines klassischen Galois-LFSR zum Einsatz, das um die mächtige Self-Shrinking-Generatorfunktion erweitert wurde. Diese sorgt für eine bedeutende kryptografische Abhärtung der LFSR-Sequenz und bringt im Zusammenhang mit dem Key-Feedback ein hohes Maß an Nichtlinearität in das Kryptosystem ein. Dabei lassen sich LFSR-basierte PRNGs vergleichsweise codeeffizient, elegant und transparent in Assembler umsetzen.

      Da RST keine Feistel-Chiffre ist, müssen Pseudozufallsvektoren für Verschlüsselung und Entschlüsselung jeweils in umgekehrter Reihenfolge angewandt werden. Daraus ergibt sich zwangsläufig, dass auf einer Seite die Pseudozufallssequenz aus dem PRNG für eine komplette Blockrunde zwischengespeichert werden muss. Auf der Gegenseite können die Zahlen aber direkt aus dem PRNG gezogen werden. Es versteht sich von selbst, dass die speicher- und codesparende Variante auf den Mikrocoontroller verlagert wird.


      Blockverschlüsselung (Pseudocode):

      load PRNG with initial key

      # PRNG()             pseudo random number generator, consecutively clocked, similar to RND()
      # RANDSET[0...63]    an array to keep 64
      preloaded PRNG vectors to be read in reverse order
      # BUFFER[0...15]     contains working data, initially loaded with plaintext block

      for i = 63 to 0 
          RANDSET[i] = PRNG (state)
          state = state + 1
      next i


      for r = 3 to 0           # outer rounds counting down 3,2,1,0
          for x = 15 to 0      # inner block cycle counting down 15 to 0
             
              y = RANDSET(r*16 + x)   # read vectors from RANDSET in reverse order 63 to 0
              ax = BUFFER[x]         
              ay = BUFFER[y]         
                     
      invert ay
                      ax = ax - ay    # substitution
                      right-shift ax, shift zero to bit 0, bit 7 into Carry
         # bitshift permutation
                     
      BUFFER[y] = ax 
                      BUFFER[x] = ay  # byte-swap elements
          next x
      next r

      BUFFER[0...15] = encrypted block
      Blockentschlüsselung (Pseudocode):

      load PRNG with initial key

      # BUFFER[0...15]         encrypted block
      # PRNG()                 deliver 4-bit pseudorandom vectors, according to state

      state = 0
      for r = 0 to 3           # outer rounds
          for x = 0 to 15      # inner block cycle
              y = PRNG(state)
              state = state + 1
              ax = BUFFER(y)   # byte-swap elements
              ay = BUFFER(x)      
                      arithmetic left-shift tmp1, shift zero to bit 0, bit 7 into Carry
                      ax = ax + ay + Carry
                      invert tmp2       
                      BUFFER(x) = ax   
                      BUFFER(y) = ay
         
          next x
      next r

      BUFFER[0...15] = decrypted block

      Zur Diskussion

      Folgende Vorteile sehe ich in der gegenwärtigen Umsetzung von "OWL-RST": Der PRNG läuft immer weiter. Jeder Krypto-Block wird mit einem komplett neuen Schlüsselsatz beackert. Eine auffällige Musterbildung, wie sie bei klassischen Blockchiffren in einem ungünstig gewählten Feedback-Modus vorkommt, ist ausgeschlossen. Hier profitiert die Blockchiffre von den Eigenschaften einer Stromchiffre.
      Der Verzicht auf Lookup-Tabellen und komplizierte Schlüssel-Transformationen spart bei der Implementierung auf Mikrocontrollern eine Menge Speicherplatz (siehe Firmware).
      Schon bei Mindestrundenzahl erreicht RST recht ordentliche Balancierungs-, Konfusions- und Diffusions-Eigenschaften. Zusätzliche Maßnahmen zum "Whitening" des Chiffrats sind überflüssig. Die Klartext-Schlüssel-Rückkopplung von RST verfolgt allein den Zweck, einen geheimen IV verwenden zu können und massive Fehlerfortpflanzung zu garantieren.

      Die Nachteile sind offensichtlich: Der PRNG läuft immer weiter. Ein kryptografisch starker PRNG braucht Rechenzeit. Auf dem PC war "RST-128" selbst in einer teiloptimierten Variante noch um das 3- bis 5-fache langsamer, als eine vergleichbare Implementierung von AES. (Mit TEA/XTEA lag es fast gleichauf!)

      Mein vorläufiges Fazit: In der Bootloader-Umgebung spielt die Performance der Krypto-Schicht eine untergeordnete Rolle. Der "Flaschenhals" sind hier auch immer die physischen Schreibzugriffe und die serielle Übertragung. Mit OWL-RST steht eine echte Blockchiffre zur Verfügung, die mit sehr kompaktem Code solide Verschlüsselungssicherheit einschließlich Fehlererkennung und Authentifizierungsfunktion bietet.
      Kritik an dieser hausgemachten Lösung ist billig und legitim. In diesem Zusammenhang möchte ich darauf hinweisen, dass die wohl kritischste Komponente des Systems, der Pseudozufallsgenerator, gar keine Eigenentwicklung ist, sondern absolut konservativ ausgewählt wurde. Es handelt sich um ein 128-Bit-LFSR mit einfachem Generatorpolynom (Galois-Feedback auf den Bits 128, 127, 126 und 121), welches durch die Self-Shrinking-Filterfunktion massiv gestärkt wurde. Das SSG-LFSR gilt als kryptografisch sicherer PRNG.
      Weiter gehe ich davon aus, dass die nachgeschaltete Blockchiffre und der IV-VI-Mechanismus keine neuen Schwachstellen aufreißen, sondern im Gegenteil sämtliche Angriffe, die auf eine Extraktion und Analyse der zugrundeliegenden LFSR-Sequenz abzielen, noch erheblich erschweren.
      Die Kollisionsfreiheit der Fehlererkennung bei RST ist meiner Einschätzung nach mit einschlägigen CRC- oder MAC-Verfahren annähernd vergleichbar. Auch hierzu höre ich gern qualifizierte Argumente und Vorschläge!


      Nach oben | Index



      Firmware

      Die OWL-Firmware ist in Assembler geschrieben und nutzt den Standard-Befehlssatz, welcher von nahezu allen 8-Bit-AVRs unterstützt wird. Die Firmware ist von keinen besonderen Hardwarekomponenten abhängig und verwendet keine Interrupts. Somit steht dieser Bootloader schon jetzt wieder für mehr als 100 verschiedene ATtinys und ATmegas zur Verfügung. Alle Varianten brauchen unter 512 Bytes. Der Quellcode ist offengelegt und reichlich kommentiert.

      Features:
      • Portabler Code, läuft auf vielen 8-Bit-AVRs
      • Nutzung beliebiger Ports für den Datenempfang
      • Schnelles "patentiertes" Verfahren für wiederholtes Neusynchronisieren und Autobauding
      • Warten bis zum Timeout oder Einstieg in laufendes Signal
      • Datenempfang in nichtinvertierter oder invertierter Logik
      • Optionales Steuersignal in nichtinvertierter oder invertierter Logik (Dummy-TXD, RS485-TE)
      • Individueller 128-Bit-Zufallsschlüssel bzw. individuelle Geräteadresse "serienmäßig"
      • Sichere Authentisierung, Entschlüsselung und Ablaufsteuerung nach "OWL-RST"
      • Lineare Schreibzugriffe in EEPROM und/oder Flash (zurzeit bis 64-K-Devices)
      • Klar definiertes Verhalten im Fehlerfall

      Speicherbelegung:


      Fußabdruck auf ATtinys:
      Fußabdruck auf ATmegas:
      • Bootloader belegt 512 Bytes am oberen Flash-Ende.

      • Aufruf: Modifizierter rjmp/jmp an Adresse $0000 springt zur Startadresse des Bootloaders (BOOTSTART).

      • Bootloader springt nach beendigtem Job oder nach Timeout zur Reset-Routine der Applikation (RESET).

      • INFO TAG mit Meta-Daten wird jeweils an das Ende eines Flash-Uploads angehängt und liefert dem Bootloader Timeout (Byte) und Sprungadresse zur Reset-Routine der Applikation (Word).

      • Krypto-Schlüssel in Bootloader eincodiert (letzte 16 Bytes der Firmware).
      • Bootloader belegt BOOT FLASH SECTION
        von 512 Bytes am oberen Flash-Ende.

      • Aufruf: Standardmäßig über BOOT RESET VECTOR (BOOTRST), welcher beim Hardware-Reset zur Startadresse der Bootloader-Sektion springt (BOOTSTART).

      • Bootloader springt nach beendigtem Job oder nach Timeout zur Adresse $0000 und startet damit die Applikation.

      • Krypto-Schlüssel und Timeout-Byte sind fest eincodiert (letzte 17 Bytes der Firmware).

      • Bootloader-Sektion kann per Lockbits umfassend geschützt werden (direkte Bootloader-Unterstützung auf ATmegas).

      Hinweis: Adressen in den Diagrammen sind Bytes.

      An dieser Stelle eine "High-Level-Beschreibung" zu wesentlichen Funktionsblöcken der  OWL-Firmware:


      Aufruf:
      Gewöhnlich erfolgt der Aufruf eines Bootloaders über einen Hardware-RESET. Dieser wird durch eine steigende Flanke auf dem Controller-Eingang "RESET" oder durch Verbinden des Controllers mit der Stromversorgung (Power-On-Reset bzw. Brown-Out-Reset) ausgelöst. Der Aufruf des Bootloaders per Hardware-Reset ist die technisch sauberste und rechtlich einwandfreie Methode, um eine klare Trennung zwischen Bootloader- und Applikations-Firmware zu gewährleisten.


      Initialisierung: Der Bootloader wird nach dem Hardware-Reset als erstes Programm gestartet. Er initialisiert den Stackpointer und alle von ihm selbst genutzten Register, Ports und Speicherzellen. Es findet keine Initialisierung des übrigen SRAM oder der sonstigen I/O-Ports statt.
      • ATtinys: Der Bootloader durchsucht absteigend den Applikations-Flash nach dem sogenannten INFO TAG und holt sich von dort das Timeout-Byte. Anschließend lädt er den individuellen Krypto-Schlüssel, der sich "hard-coded" am obersten Flash-Ende befindet, in die PRNG-Arbeitsregister (r0-r15). Dann beginnt der Bootloader auf der Empfangsleitung zu lauschen. Erscheint dort vor Ablauf des Timeout ein Signal, dann versucht der Bootloader, sich darauf zu synchronisieren. Passiert bis zum Timeout nichts, holt sich der Bootloader aus dem INFO TAG die Adresse der Reset-Routine der Applikations-Firmware und startet diese. Bei "leerem" Flash (keine Applikation, alles $FF-Bytes) verwendet der Bootloader immer den längstmöglichen Timeout und startet sich selbst wieder. In dieser Ausgangslage bleibt der Bootloader also permanent erreichbar und muss nicht immer wieder resettet werden.

      • ATmegas: Der Bootloader lädt den individuellen Krypto-Schlüssel in die Arbeitsregister r0-r15 und beginnt auf der Empfangsleitung zu lauschen. Der Timeout ist auf ATmegas fest in die Firmware eincodiert, hier wird auf den INFO TAG vollständig verzichtet. Trifft vor Ablauf des Timeout ein Signal ein, so wird der Bootloader versuchen, sich darauf zu synchronisieren. Passiert bis zum voreingestellten Timeout nichts, springt der Bootloader pauschal zur Adresse $0000, wo die Applikation auch ohne Reset-Vektor gestartet worden wäre. Bei ansonsten leerem Flash wird der Bootloader also auch hier immer wieder neu gestartet.

      Synchro-Autobauding:
      Der Bootloader wartet an der für den Datenempfang konfigurierten Leitung bis zum Timeout auf einen ersten Pegelwechsel. Dieser wird verworfen, um ein "Einpendeln" des Signals zu ermöglichen. Anschließende Pegelwechsel wertet die Firmware mit dem weiter oben beschriebenen Synchro-Autobaud-Verfahren aus. Hier sind eine Menge Erfahrungswerte von "TSB" eingearbeitet worden. Sofern das ankommende Signal tatsächlich eine OWL-Präambel ist, und sofern das Signal ausreichend flankensteil durchkommt, wird die Erstsynchronisation gelingen. Danach besitzt der Bootloader eine präzise Zeitbasis für den Empfang des ersten Datenblocks per Software-Decoder. Der Synchro-Autobaud-Zyklus wird vor jedem einzelnen Datenblock wiederholt, sodass die Transmission gegenüber Schwankungen der Taktfrequenzen auf beiden Seiten nahezu immun wird.


      Blockdatenempfang: Nach erfolgreichem Synchro-Autobauding werden die nachfolgenden Zeichen über die reguläre Empfangsroutine decodiert. Zunächst wartet eine Schleife die restlichen Präambel-Zeichen ab, bis das Blockstart-Zeichen erscheint. Die darauf folgenden 16 Bytes sind der verschlüsselte Datenblock und werden zur weiteren Verarbeitung in einen SRAM-Puffer übernommen.


      Block-Daten entschlüsseln: Der Bootloader klinkt sich aus der seriellen Übertragung aus und beginnt die Entschlüsselung des im SRAM-Puffer vorliegenden Datenblocks. Für 4 Runden auf 16 Bytes werden insgesamt 64 Pseudozufallsvektoren à 4 Bit aus dem PRNG gezogen (Mindestrundenzahl). Die vom PRNG gelieferten Pseudozufallsvektoren hängen vom inneren Zustand (state) des PRNG ab, welcher in den Registern r0-r15 gespeichert ist. Mit jedem gezogenen Bit verändert sich der innere Zustand des PRNG.
      Nach dem Entschlüsseln liegen die 16 (mutmaßlich) fehlerfreien Bytes im selben Puffer vor.
      Der frisch entschlüsselte Block wird per XOR auf die PRNG-Register r0-r15 rückgekoppelt (Key Feedback). Dadurch fließt Entropie aus den Nutzdaten in die nachfolgende Ver/Entschlüsselung ein und die massive Fehlerfortpflanzung wird garantiert.
      Der erste Block einer neu begonnenen Sequenz, der IV-Block, besteht aus Zufallszahlen. Faktisch läuft der PRNG ab dem zweiten Block einer Sequenz mit einem völlig neuen Zufallsschlüssel weiter, der auch nur einmal verwendet wird. Außerdem wird der IV-Block als VI in einen zweiten SRAM-Puffer kopiert.
      Alle danach entschlüsselten Blöcke werden mit dem VI verglichen. Solange der aktuelle Block nicht mit dem VI identisch ist, geht das Programm davon aus, dass es sich um reguläre Schreibdaten handelt, die entsprechend weiterverarbeitet werden.
      Erkennt das Programm, dass der aktuelle Block mit dem VI identisch ist, dann ist die Sequenz erfolgreich abgeschlossen und der Bootloader weiß jetzt, dass alle vorherigen Blöcke in Ordnung waren. Dann schaltet er zur nächsten Sequenz weiter.
      Im Fehlerfall wird überhaupt kein VI mehr erkannt. Das Programm verharrt in der aktuellen Sequenz, bis die Übertragung zuende ist und es zum Timeout kommt. Weiteres dann unter "Fehlerbehandlung".
      Die gesamte Blockentschlüsselung benötigt in Assembler einschließlich PRNG gerade einmal 50 Maschinenbefehle! Der Blockvergleich und das XOR-Feedback auf den Schlüsselgenerator konnten in einer gemeinsamen Schleife untergebracht werden, die auch nur 12 Maschinenbefehle braucht.


      Authentisierungs-Sequenz (S1): Bevor der Bootloader irgendwelche Schreibzugriffe zulässt, muss er sichergehen, dass der Sender das Schlüsselgeheimnis kennt. Könnte ja sonstwer daherkommen. Ein "Türsteher" ist nötig, damit der Bootloader bereits dichtmachen kann, bevor Datenmüll in den EEPROM geschrieben wird.
      Anders, als eine simple Passwort-Abfrage, ist die Authentisierung gegenüber dem Bootloader "nicht übertragbar". Hier wird eine komplette RST-Sequenz gesendet, die aufgrund des Key-Feedbacks untrennbar mit der nachfolgenden EEPROM- und Flash-Sequenz verbunden ist.
      Wenn der Bootloader den dritten Block der Authentisierungs-Sequenz S1 als VI erkannt hat, dann weiß er mit allergrößter Sicherheit, dass der Sender den korrekten Schlüssel benutzt. Dann geht der Bootloader vertrauensvoll in die nachfolgende EEPROM-Sequenz S2.
      In allen anderen Fällen, also bei Verwendung eines falschen Schlüssels oder bei gestörter Übertragung, wird die Authentisierungs-Sequenz S1 nicht als gültig erkannt. Der Bootloader geht in eine Endlos-Schleife ohne Timeout. Dieser Zustand kann nur über einen erneuten Hardware-Reset beendet werden.
      Der Blockade-Mechanismus erlaubt es, mehrere Bootloader mit verschiedenen Schlüsseln und unterschiedlichen technischen Voraussetzungen auf einer gemeinsamen Programmierleitung zu betreiben. Pro Reset-Zyklus wird immer nur der tatsächlich angesprochene Bootloader die für ihn bestimmte Übertragung auswerten. Alle nicht angesprochenen Bootloader werden ab dem dritten Block in den Blockadezustand übergehen und sich bis zum nächsten Hardware-Reset vollkommen passiv verhalten. Eine dort vorhandene Applikations-Firmware wird nicht angetastet und nicht unkontrolliert gestartet. (Solche Multi-AVR-Szenarien sind im Zusammenhang mit TSB von einigen Leuten getestet worden, aber hier gab es wegen des eher primitiven Passwort-Verfahrens immer wieder Probleme.)


      EEPROM-Sequenz (S2):
      Der Bootloader entschlüsselt und kopiert den IV der EEPROM-Sequenz. Die nachfolgenden Datenblöcke werden in Schüben von 16-Bytes im Atomic-Write-Modus in den EEPROM geschrieben. Enthielt die EEPROM-Sequenz keinen einzigen Datenblock (nur IV- und VI-Block), dann wird im EEPROM auch nichts verändert und der Bootloader geht über zur Flash-Sequenz S3.
      Für den EEPROM erfolgt kein separater Löschzyklus. Das bedeutet, Speicherinhalte, die sich weiter "hinten" im EEPROM-Adressbereich befinden, werden nicht angetastet, wenn ein neuer Schreibzugriff nur tiefer liegende Adressen berührt. Das kann gegebenenfalls für eine Art "inkrementelle" EEPROM-Updates ausgenutzt werden.
      Zum Löschen des gesamten EEPROM muss eine Sequenz übertragen werden, die den ganzen Speicherbereich abdeckt und mit $00 oder $FF überschreibt.
      Im EEPROM-Modus müssen keine besonderen Vorkehrungen gegen Adressüberlauf getroffen werden, da im EEPROM kein ausführbarer Code stehen kann. Sollte in der EEPROM-Sequenz etwas gründlich schiefgehen, dann würden die Schreibzugriffe einfach nur immer wieder den EEPROM überschreiben. Dieses Risiko erscheint tragbar. Der EEPROM ist gewissermaßen die "Knautschzone" vor dem wirklich kritischen Flash-Zugriff.
      Kommt es in der EEPROM-Sequenz zum Timeout, dann geht der Bootloader in den Blockadezustand, sodass auch hier die indirekte Standard-Rückmeldung "Hey, das war wohl nichts!", erfolgt.
      Wurde die EEPROM-Sequenz korrekt mit dem VI abgeschlossen, dann erwartet der Bootloader als Nächstes die Flash-Sequenz S3.


      Flash-Sequenz (S3): Der Bootloader entschlüsselt und kopiert den IV der Flash-Sequenz. Wenn der darauf folgende Block bereits der VI ist, dann ist der Bootloader schon fertig und wird den Flash unangetastet lassen.
      Kommen nach dem IV jedoch Flash-Schreibdaten, dann löscht der Bootloader zunächst den gesamten Applikations-Flash unterhalb der Bootloader-Firmware. Der Löschzyklus erfolgt auf ATtinys mit Rücksicht auf die besonderen Risiken Top-to-Bottom. Generell muss der Bootloader Flash-Daten, die ja immer in Blöcken von 16 Bytes eintreffen, bis zur tatsächlichen Seitengröße (PAGESIZE) zusammenfassen, bevor er sie in einem Rutsch in die aktuelle Page schreiben kann.
      Durch die Teilung in 16-Byte-Einheiten ist die Flash-Schreibroutine recht zukunftssicher. Sie würde im Prinzip noch bis zu einer Pagesize von 4096 Bytes funktionieren... (Die größte auf ATmegas eingesetzte Pagesize beträgt 256 Bytes.)
      Auf ein explizites Verifying der geschriebenen Daten wird jetzt komplett verzichtet. Die langjährigen Erfahrungen mit TSB haben gezeigt, dass es NIE zu fehlerhaften Flash-Schreibzugriffen kommt, sobald die Daten erst einmal fehlerfrei im Schreibpuffer gelandet sind und für die Dauer des Flash-Write stabile Betriebsbedingungen bestehen. Beim OWL entschärft sich die Situation noch, da der gesamte Übertragungsweg ja durch das Kryptosystem abgesichert ist.
      Wurde der letzte VI aus S3 erkannt, dann war die Transmission im Ganzen erfolgreich. Bereits geschriebene Daten sind mit allergrößter Wahrscheinlichkeit fehlerfrei und dürfen in den jeweiligen Speicherbereichen stehen bleiben. In diesem Fall ist der Bootloader auch schon fast am Ende.
      Wurde kein VI erkannt, dann hat der Bootloader mit dem Ablauf des Timeout die schreckliche Gewissheit, dass in der Flash-Sequenz etwas schief gelaufen ist. Jetzt wird der Bootloader konsequenterweise den Applikations-Flash wieder löschen, damit hier kein fehlerhafter Code stehen bleibt.


      Erfolgreiche Transmission und Übergabe an Applikations-Firmware:
      Nach erfolgreichem Abschluss der Flash-Sequenz S3 übergibt der Bootloader praktisch verzögerungsfrei an die neu geschriebene oder an eine unverändert gelassene Applikations-Firmware.
      Auf einem ATtiny muss der Bootloader noch einmal nach dem INFO TAG suchen, welcher mit einer neuen Firmware ebenfalls neu geschrieben wurde. Dort steht dann der aktuelle Reset-Vektor der Applikations-Firmware als absolute Adresse. Diese springt der Bootloader per indirektem Jumpbefehl an und startet somit die Applikations-Firmware.
      Auf einem ATmega muss der Bootloader nur den Zugriff auf den RWW-Speicherbereich (= Applikations-Flash) freigeben. Dann springt er pauschal nach $0000, wo sich üblicherweise die Interrupt-Tabelle mit dem unveränderten Original-Reset-Vektor der Applikation befindet, und die Applikation startet.
      Günstig ist es also, wenn sich die Applilkation irgendwie bemerkbar machen kann, also zum Beispiel mit ihrem Programmstart eine LED zum Leuchten bringt, eine Display-Meldung ausgibt oder einen Piepser aktiviert. Damit erhalten wir eine indirekte aber klare Rückmeldung über den Erfolg der Transmission.


      Allgemeine Fehlerbehandlung:
      Erste Fehler können schon auftreten, noch bevor irgendwelche Daten geflossen sind, insbesondere bei einem Hardware-Reset per Kaltstart. Hier kann auf der Empfangsleitung für kurze Zeit ein unzulässiger Low-Pegel anliegen, der natürlich nicht von einem seriellen Datensignal kommt. Oder die externe Hardware verursacht einen oder mehrere Pegelwechsel auf der Empfangsleitung, bis sich die Versorgungsspannungen stabilisiert haben. Wenn zu diesem Zeitpunkt bereits ein Bootloader auf der Leitung lauscht, kann es vorkommen, dass sich dieser infolge des ungültigen seriellen Signals "aufhängt". Solche unschönen Effekte gab es anscheinend mit TSB auf USB-Geräten. Workarounds haben sich dann wieder in anderen Anwendungen als hinderlich erwiesen.
      Der OWL zeigt ein in mehrfacher Hinsicht verbessertes Startverhalten. Sollte die Empfangsleitung zu Anfang auf Low liegen, "brummen" oder irrtümlich ein paar serielle Zeichen reinkommen, die nicht für den Bootloader bestimmt sind, dann kommt zwar auch keine Bootloader-Sitzung zustande, aber der Bootloader wird sich nach dem Abklingen der Störung ganz normal den voreingestellten Timeout starten und danach an die Applikations-Firmware abgeben.
      Erst nachdem mindestens eine gültige Präambel ausgewertet und ein erster Datenblock komplett entschlüsselt wurde, geht die Bootloader-Firmware davon aus, dass dies kein Versehen sein kann und eine reguläre OWL-Transmission vorliegt. Sollte es in diesem fortgeschrittenen Stadium zu einem Timeout kommen, dann übergibt der Bootloader nicht mehr an die Applikations-Firmware. Also: Ein bisschen "Gekruschel" auf der Leitung direkt nach dem Reset wird ignoriert. Danach gilt: ENTWEDER kam alles vollständig und fehlerfrei und im Rahmen des Timeout durch, dann wird, wie oben erwähnt, die Applikation unmittelbar nach Beendigung der Transmission gestartet, ODER es gab irgendeinen Fehler oder einen Timeout während der Übertragung, dann geht der Bootloader in den Blockadezustand.

      Timeout-Timing: Der Timeout des Bootloaders soll in einem sehr breiten Fenster von realistischen Taktraten (etwa 128 kHz bis 25 MHz) Verzögerungen von einer zehntel Sekunde bis hin zu mehreren Sekunden ermöglichen. Hierfür gibt es gute Nachrichten: Der OWL verwendet ebenfalls ein "Timeout-Byte",  welches aber gewissermaßen normiert ist. Dafür wird der Basiszähler für die Timeout-Zeitschleife auf die vorgesehene Clock-Frequenz kalibriert. Wenn wir beim Erzeugen der Target-Firmware die vorgesehene Taktfrequenz einigermaßen zutreffend angegeben haben, ist die Einheit der Timeout-Bytes immer genau 1/100stel Sekunde. Das bedeutet, der Wert "100" für das Timeout-Byte entspricht immer einer Sekunde, der Wert "1" einer Hundertstel Sekunde, und der Wert "255" entspricht 2,5 Sekunden. (Sollte dieser Spielraum nicht ausreichen, dann besteht noch die Möglichkeit, eine höhere Frequenz anzugeben, als tatsächlich verwendet wird.)
      Die Anpassung der Zeitbasis-Schleife in der Routine "TimeOutStopState " erfolgt ähnlich, die wie Anpassung der Portzugriffe, nämlich indem die im Template eindeutig erkennbare Stelle im Code gefunden und mit neu berechneten Opcodes besetzt wird.


      PRNG (Schlüsselgenerator): Der PRNG wird bei Aufruf des Bootloaders mit dem geheimen Schlüssel geladen. Dieser innere Zustand des PRNG verändert sich bei fortlaufender Taktung und er wird außerdem über den Klartext jedes entschlüsselten Blockes modifiziert (siehe Diagramm zum Key-Feedback).
      Der PRNG ist die Software-Implementierung eines klassischen 128-Bit LFSR mit Rückführungen von den Bits 128, 127, 126 und 121 (als Galois-XOR mit einem Byte realisierbar). Der Output geht durch ein sogenanntes Self-Shrinking-Filter. Diese Funktion macht aus dem einfachen LFSR mit eher mäßigen Autokorrelationseigenschaften einen kryptografisch starken Pseudozufallsgenerator. Allerdings braucht das SSG-LFSR im Durchschnitt 3 mal mehr Taktzyklen, als ein ordinäres LFSR. Dieser Nachteil erscheint in der Bootloader-Anwendung tolerierbar, da Sicherheit an erster Stelle steht und andere Faktoren den Datendurchsatz stärker drosseln.
      Nichtzuletzt ließ sich der Assemblercode für das SSG-LFSR deutlich optimieren. Man lernt ja dazu... Hier erfolgen die Bitshifts auf je zwei Arbeitsregistern (statt über alle 16), und nur mit jedem 8.Takt werden die übrigen 14 Register dann direkt als Bytes geshiftet ( mov), was eine ganze Menge Proztessortakte einspart.
      Meiner Ansicht nach ist das vorliegende SSG-LFSR eine der takt- und codeeffizientesten PRNG-Optionen auf 8-Bit-MCUs, und es ist eine Schande, dass ich mal wieder selbst drauf kommen musste, weil sich nichts Vergleichbares im Netz fand! Die unregelmäßige Taktung könnte weitere Vorteile hinsichtlich möglicher Seitenkanalangriffe bedeuten (z.B. "Power analysis", dies müsste jedoch ausführlicher untersucht werden).


      Port-Limits: Die Firmware kann nur auf I/O-Ports zugreifen, die über die Maschinenbefehle cbi, sbi, sbic, sbis direkt erreichbar sind. Einige exotische Devices kennen mittlerweile auch einen "PORTG" oder "PORTH" mit I/O-Adressen oberhalb von $3F. Diese Ports sind infolge der AVR-Prozessorarchitektur nur über SRAM-Befehle adressierbar. Das die entsprechenden Opcodes ein langsameres Timing haben und mehr Speicherplatz kosten, werden solche "memory mapped"-Zugriffe von der OWL-Firmware bis auf Weiteres nicht unterstützt.


      Code-Flexibilität im Vergleich zu TSB: Der Assembler-Quelltext der OWL-Firmware enthält auch wieder einige Präprozessor-Anweisungen, die den Code flexibel machen. Dennoch ist der Anteil solcher  .if/.endif-Konstrukte zur bedingten Assemblierung deutlich geringer, als dies noch beim TSB der Fall war. Schließlich ist das zugrundeliegende Übertragungsformat ("OWL-Transmission") für alle Devices einheitlich, während Besonderheiten im Timing bereits auf Senderseite in Form der maßgeschneiderten Präambeln berücksichtigt werden. Auch benötigt der OWL keine zusätzliche Speicherseite ("LASTPAGE"), sodass sich im Vergleich zu TSB eine ganze Page einsparen lässt. Weniger Extrawürste und  aufgeräumterer Code - Ich bin guter Hoffnung, dass der OWL-Code noch wartungsfreundlicher sein wird, als sein Vorgängerprojekt.


      Portierbarkeit: Der vorliegende Assemblercode ermöglicht ohne besondere Anpassungen die Erzeugung von OWL-Firmware für einen Kernbestand von ca. 100 ATtinys und ATmegas mit bis zu 64 Kilobytes an Flash.
      Zahlreiche ATtinys und ATmegas sind in der Vergangenheit erfolgreich mit TSB gelaufen. Für einige Chips waren kleinere Anpassungen am Code erforderlich, die glücklicherweise nicht neu erarbeitet werden mussten. Es besteht also eine große Wahrscheinlichkeit, dass der OWL auf denselben Devices von Anfang an problemlos arbeiten wird.
      AVR-Devices über 64 KiB (z.B. Mega128x und Mega256x) verlangen nach einer etwas dickeren Extrawurst. Diese Chips haben 128 bzw. 256 Kilobyte an Flash-Speicher, welcher sich bei Flash-Writes nicht mehr allein mit dem 16-Bit-Z-Register erfassen lässt. Für den erweiterten Zugriff kommt eine Art "Bankswitching" zur Anwendung (I/O-Register RAMPZ). Ein One-Way-Loader für diese Devices erscheint möglich, aber unter Beibehaltung des linearen Adresszugriffs wäre das vielleicht nichts für Ungeduldige. Im Extremfall dauert das Firmware-Update für den vollen Applikations-Flash von 128 oder gar 256 Kilobytes nicht mehr Sekunden, sondern Minuten. Ein erweitertes Protokoll für den "modularen" Schreibzugriff (einzelne Bänke oder Pages) könnte die Situation etwas entschärfen; ob das aber eine gute Idee ist, da habe ich ernsthafte Zweifel. Denn wenn der gute Bootloader hier und dort ein paar Kilobytes überschreibt, während an anderen Stellen ausführbarer Code stehenbleibt, ist das Chaos eigentlich vorprogrammiert. Es gibt ja in einem abgesicherten Chip keine Möglichkeit, Daten zurückzulesen, zumal dies dem ganzen Sicherheitskonzept des OWL komplett widersprechen würde. Nun, genug spekuliert. Hier bin ich auf Anregungen und Tipps von Leuten angewiesen, die solche Dinger in der Praxis tagtäglich einsetzen. Ich selbst habe eine kleine Testumgebung mit Mega1284 und schaue mir das demnächst mal an!
      Mein Motivationsspielraum endet jedoch bei den "XMegas"! Mit ein paar Code-Anpassungen ist es da nicht mehr getan, die ganze Architektur weicht doch sehr stark von den "klassischen" AVRs ab. Die Unterschiede zwischen "ATmegas" und "XMegas" hinsichtlich I/O-Konzept und Interrupts erscheinen mir gegenwärtig größer, als etwa zwischen ATmegas und PICs. Ich nutze keine XMegas. Eine Portierung für XMegas oder PICs steht auch nicht auf meiner To-Do-Liste, sorry!

      Fuses/Lockbits:

      Für den Betrieb eines Bootloaders muss der Controller gewisse Voraussetzungen erfüllen.

      ATtinys:
      • SELFPRGEN aktivieren (na klar, sonst kann OWL später nichts in den Flash schreiben!)
      • BODLEVEL aktivieren verhindert Flash-Korrumpierung bei unstabiler Betriebsspannung (Ein- und Ausschalten).
      • Lockbits Modus 3 verhindert das Ausspionieren oder Verändern von Speicherinhalten über die ISP/JTAG.
      ATmegas:
      • BOOTRST aktivieren aktiviert den direkten Bootloader-Aufruf per Hardware-Reset.
      • BODEN + BODLEVEL aktivieren verhindert Flash-Korrumpierung bei unstabiler Betriebsspannung.
      • BOOTSZ=10 oder BOOTSZ=11 zur Verwendung einer Bootloader-Sektion von nur 512 Bytes (256 Words).
      • BLB in Modus 2 oder 3 schützt die Bootloader-Sektion vor unkontrollierten Schreibzugriffen.
      • Lockbits in Modus 3 verhindert das Ausspionieren oder Verändern von Speicherinhalten über ISP/JTAG.

      Kompatibilitäts-Voraussetzungen und Vorsichtsmaßnahmen:

      • Keine Abhängigkeiten. Die Bootloader-Firmware darf nicht von weiteren Firmware-Komponenten abhängig sein, da sie sonst nicht in der Lage wäre, auf einem "leeren" Controller eine erste Applikations-Firmware zu laden.
        Umgekehrt wäre der Aufruf von vorhandenem Bootloader-Code durch eine Applikation zwar durchaus möglich, aber meiner Meinung nach nicht empfehlenswert. Eine solche "Verzahnung" von Programmen führt fast zwangsläufig zu technischen Problemen und bei eher restriktiven Lizenzmodellen auch zu großen rechtlichen Problemen, wenn nicht alles aus einer Hand stammt.
        Generell vertrete ich die Auffassung, dass Applikations-Firmware und Bootloader-Firmware auf einem Mikrocontroller in keiner Weise voneinander abhängig sein dürfen und sauber getrennt werden sollten.
        Das einzig legitime Zusammenspiel zwischen einer Bootloader- und einer Applikations-Firmware soll darin bestehen, dass der Bootloader nach getaner Arbeit (d.h. Timeout oder erfolgtes Firmware-Update) die Kontrolle an die Applikation abgibt.

      • Applikations-Firmware und Bootloader-Firmware dürfen zusammen nicht mehr Speicherplatz belegen, als tatsächlich vorhanden ist...   Logo, aber keine Sorge, wenn's nicht passt, wird sich die Software schon melden.
      • Vorsichtsmaßnahmen ATtinys: Die Applikation sollte am besten auf Flash-Schreibzugriffe verzichten, da es auf ATtinys möglich ist, den Bootloader durch fehlgeleitete Schreibzugriffe zu beschädigen oder durch Auslesen des Bootloader-Adressbereichs Schlüsselmaterial zu "leaken".

      • Vorsichtsmaßnahmen ATmegas: Die Bootloader-Sektion kann per Fusebits gegen Zugriffe aus der Programmsektion geschützt werden. Hier wird der Bootloader nahezu unsterblich und es sind keine weiteren Vorsichtsmaßnahmen erforderlich.

      Nach oben | Index




      Software

      Allgemeines

      Die OWL-Software ist ein Kommandozeilentool für die PC-Plattform. Das Programm steht im Quellcode sowie als ausführbare Datei für Windows (32 Bit) und Linux (32/64-Bit) zur Verfügung. Das Programm kann Folgendes:
      • Erzeugung von Einzel-Bootloadern mit angepassten Ports und Zufallsschlüsseln
      • Erzeugung von Serien-Bootloadern mit angepassten Ports und Zufallsschlüsseln
      • Infos zu unterstützten Controller-Modellen und Hardware-Optionen
      • Verwaltung aller selbst generierten Bootloader, Schlüssel und Meta-Daten über frei wählbare Dateinamen
      • Senden von Daten für Flash und/oder EEPROM in einer Sitzung ("Transmission")
      • Export kompletter Transmissionen in eine Datei für Distributionszwecke
      • Import verschlüsselter Transmissionen und Weiterleitung auf lokale Zielgeräte
      • Test der Krypto-Module
      • Hilfesystem

      Philosophie

      So einfach wie möglich, aber nicht einfacher! Meine Hardware-Software-Projekte setzen auf einfache Verwaltungsstrukturen, größtmögliche Transparenz und minimale Abhängigkeiten. Haltet mich für verrückt, aber ich gehe weiterhin davon aus, dass die Technik dem Menschen dienen soll und dass digitale Versklavung kein unentrinnbares Schicksal ist. Wer Technik souverän einsetzt, wer den Unterschied zwischen gegenseitigem Nutzen und einseitigem Benutztwerden kennt, und wer auf Nutzloses verzichten kann, der wird in Zukunft umso mehr Spaß haben und seine privaten wie geschäftlichen Geheimnisse effektiv schützen können. (Die anderen haben halt Pech gehabt.)

      Nun hat die OWL-Software schon einen vergleichsweise großen Funktionsumfang. Und das an der Kommandozeile! Kryptische Zeichenketten, Kraut-und-Rüben-Syntax, abartige Unterscheidung zwischen Groß- und Kleinschreibung, verschachtelte Abhängigkeiten, ätzende Semantik...

      Aber nicht hier! Das Programm verfügt über einen menschenfreundlichen Kommandozeilen-Parser und vergleichsweise informative Hilfe-Texte und Bildschirmmeldungen . Für jede Kommandozeilenoption gibts eine "sprechende" Langschreibweise und eine einprägsame Kurzschreibweise. Meinem Parser ist die Reihenfolge der Optionen und Argumente völlig egal (lateinische Semantik!) Alles, was sich der  Nutzer merken muss, um eine bestimmte Funktion auszulösen, ist der Name der dafür benötigten Option und eventuelle weitere Parameter, die zusätzlich angegeben werden müssen oder können. Vieles ergibt sich bereits durch Nachdenken, den Rest können wir nachschlagen. Wer jemals etwas an der Kommandozeile gemacht hat, für den dürfte dieses OWL-Tool ungewöhnlich "intuitiv" bedienbar sein. Ich behaupte sogar: Im Gegensatz zu gewissen 'dudes' ist mein OWL-Kommandozeilentool auch ohne GUI-Frontend benutzbar!

      Sämtliche Interaktionen, Schlüsselwörter und Bildschirmmeldungen sind in der Sprache Englisch gehalten. Das ist nun einmal der linguistisch und technisch günstigste Kompromiss. (Weitere Sprachversionen sind für diese Anwendung vorerst nicht geplant.)

      Installation

      Die Software ist portabel , d.h. sie läuft in jedem Verzeichnis, in dem wir Schreib- und Dateiausführungsrechte haben. Natürlich läuft das Programm auch von einem externen Medium, wie etwa einem USB-Stick. Zur "Installation" einfach das Download-Paket an den gewünschten Zielort entpacken. Dabei werden folgende Verzeichnisse angelegt:
      • owl
        • templates
        • targets
        • transmissions  
      Der spätere "Umzug" mit einer kompletten OWL-Umgebung (Hauptordner samt Unterordnern) ist kein Problem. Die Anwendung selbst speichert keine absoluten Pfade.


      Ordnerstruktur

      Es gibt drei "Datentypen", die die OWL-Software verwalten muss:  Bootloader-Vorlagen, Bootloader-Firmware, und Bootloader-Transmissionen . Diese liegen in separaten Dateien und Ordnern vor. Wer es gewohnt ist, seine Daten über das Dateisystem zu organisieren, wird problemlos den Überblick behalten und für den ist diese Software auch keine Black Box.
      Bootloader-Vorlagen:     /templates
      Für jedes direkt unterstützte AVR-Modell gibt's fertig assemblierten Maschinencode. Dieser enthält für das jeweilige Device eine OWL-Firmware mit Default-Ports (B0/B1) und Default-Key ($0011...EEFF). Wenn die OWL-Software einen maßgeschneiderten Bootloader erzeugen soll, dann sucht sie standardmäßig im Ordner templates nach einer Hex-Datei mit dem passenden Namen, um ihn nach Kundenwunsch anzupassen. Wer über eine AVR-Assembler-Infrastruktur verfügt und weiß, was er (oder sie) tut, kann auch eigene Templates in diesen Ordner legen.

      Bootloader-Firmware:     /targets
      Die Erzeugung eines neuen Bootloaders (Target) erfolgt nach bewährtem Prinzip auf Grundlage eines Templates für den entsprechenden Controller-Typ (Device). Das Programm durchforstet den Maschinencode nach I/O-Befehlen, die sich auf die Standard-Ports für Templates beziehen (cbi,sbi, sbic, sbis an Port B0/B1) und passt diese an die vom Benutzer gewünschten Ports an. Außerdem wird ein zufälliger Krypto-Schlüssel für den neuen Bootloader erzeugt und in den Code eingefügt.
      Schließlich speichert das Programm die modifizierte Bootloader-Firmware in eine Hex-Datei unter dem gewünschten Target-Namen (oder automatisch generiertem Namen) im Ordner targets ab. Die Datei im Format Intel-Hex soll von einem "AVR-Brenner" übernommen und per ISP in den Ziel-Controller geschrieben werden. Nach dem Ändern der Fusebits ist der neue OWL einsatzbereit.
      Die Target-Datei ist der einzige Speicherort für Krypto-Schlüssel und Meta-Daten eines Bootloaders!
      Also besser nicht löschen, wenn wir den betreffenden OWL tatsächlich benutzen wollen.
      Die Meta-Informationen zum jeweiligen Target sind als Kommentarzeilen hinter den letzten Hex-Record angehängt, menschenlesbar und editierbar. Eine ISP-Software wird diese Zeilen einfach ignorieren. Die OWL-Software wertet diese Zeilen aus und hat sofort alle benötigten Meta-Infos zum angegebenen Target parat. Alle wichtigen Informationen zu einem individuellen Bootloader sind somit in einer Datei zusammengefasst. Das Umbenennen, Kopieren, Verschieben und Modifizieren von Target-Dateien ist mit Bordmitteln jederzeit möglich. Also auch hier: Klare, einfache Strukturen, kein Datenbankschwachsinn, kein XML, kein SQL!

      Bootloader-Übertragungen:     /transmissions
      Die Software kann den Datenstrom für eine Bootloader-Übertragung an die angegebene serielle Schnittstelle senden, oder in eine Datei umleiten, welche standardmäßig in den Ordner transmissions  geschrieben wird. Dabei handelt es sich um Binärdateien mit der Endung " .owl". Durch die Speicherung geht keine Timing-Information der ursprünglichen seriellen Übertragung verloren. Die Transmissions-Datei enthält ein vollständiges Firmware-Update mit Authentisierung und Daten für EEPROM und/oder Flash.
      Die OWL-Software kann eine ".owl"-Datei übernehmen und an eine serielle Schnittstelle senden. Dabei wird automatisch die richtige Baudrate verwendet, da diese in ASCII-Codierung an das Ende der Binärdatei angehängt ist. Weitere Meta-Infos enthält das Dateiformat für OWL-Transmissionen nicht.
      Es ist daher auch möglich, eine OWL-Datei per Datenumleitung an eine serielle Schnittstelle umzuleiten. Auch damit erhalten wir eine technisch einwandfreie OWL-Transmission.
      Konsolenbeispiel DOS/Windows:
      mode COM1 9600,n,8,1 | copy /b transmission0815.owl COM1
      Gleiches unter Linux:
      stty -F /dev/ttyS0 9600 cs8 -cstopb -parenb | cat transmission0815.owl >/dev/ttyS0


      Kompilation der Transmission

      Die Software braucht einen gültigen Target-Namen als Referenz zu dem Bootloader, für den sie eine Transmission erzeugen soll. Sofern die Target-Datei gefunden wurde, kennt das Programm mit einem Schlag den Krypto-Schlüssel und alle Meta-Infos, um für dieses bestimmte Gerät eine verschlüsselte Übertragung mit korrektem Timing zu berechnen.
      Außerdem sollte natürlich eine Quelldatei mit Daten für den Flash- und/oder EEPROM angegeben werden. Oder mindestens ein Flash- oder EEPROM-Löschbefehl.
      Ein serieller Port muss nur angegeben werden, wenn die Transmission "live" über eine lokale serielle Schnittstelle gesendet werden soll. Wird kein serieller Port angegeben, dann geht der Datenstrom in eine sogenannte Transmissions-Datei (Endung .owl) im Ordner transmissions (siehe weiter unten). Weitere optionale Angaben und Modifikatoren sind möglich (bitte Hilfe-Texte konsultieren).
      Das Tool erzeugt die OWL-Transmission zweckmäßigerweise zunächst im Arbeitsspeicher, und zwar in Reihenfolge der RST-Sequenzen:
      1. Authentisierungssequenz (S1): Die erste Sequenz besteht nur aus IV, einem Dummy-Block (Zufallszahlen) und VI. Der PRNG wird mit dem Bootloader-Schlüssel geladen. Der verschlüsselte String für die Authentisierungs-Sequenz S1 hat zusammen mit IV und VI immer eine Länge von 3 Blöcken, entsprechend 48 Krypto-Bytes. Der String für S1 wird mit der längeren Einleitenden Präambel versehen. Im Abstand der Krypto-Blöcke werden Mindest-Präambeln und Blockstarter eingefügt.
      2. EEPROM-Sequenz (S2): Das Programm liest EEPROM-Daten aus dem angegebenen Hexfile und füllt diese gegebenenfalls bis zur nächsten Blocklänge auf (Padding mit Nullbytes). Der EEPROM-Datensatz wird mit IV und VI "umrahmt" und auf Grundlage des momentanen Schlüssels per RST verschlüsselt. In einem zweiten Durchlauf fügt das Programm zwischen den Krypto-Datenblöcken die notwendigen Präambeln ein. Diese berücksichtigen die Mindestdauer zur Entschlüsselung der Blöcke und die EEPROM-Schreibzeit für je 16 Bytes am Stück. Falls keine EEPROM-Daten vorliegen, besteht S2 überhaupt nur aus dem verschlüsselten IV- und VI-Block im Abstand einer Mindest-Präambel. Der fertiggestellte String für S2 wird an den String S1 angehängt.
      3. Flash-Sequenz (S3): Das Programm liest die Flash-Daten aus dem angegebenen Hexfile und füllt die letzte bereits angebrochene Page mit Zufallsbytes (und gegebenenfalls einem INFO TAG für ATtiny) auf. Der Flash-Datensatz wird auf Grundlage des momentanen Schlüssels zusammen mit IV und VI verschlüsselt und es werden die verlängerten Präambeln für Flash-Erase und Flash-Writes zwischen die Flash-Krypto-Blöcke eingefügt. Gegebenenfalls wird noch eine optionale abschließende "Präambel" hinzugefügt. Dieser letzte Teilstring wird dem bereits kombinierten String von S1 und S2 angehängt.

      Einzel-Transmission

      Wenn im Transmissions-Modus eine konkrete serielle Schnittstelle angegeben ist, etwa --serialport="COM2", sendet die Software den soeben erzeugten OWL-Datenstrom direkt über diese Schnittstelle aus. Es wird die Default-Baudrate aus der Target-Datei verwendet. Wurde an der Kommandozeile mit  --baudrate=xxxx eine abweichende Baudrate angegeben, wird diese verwendet. Die Software wird versuchen, die angegebene Baudrate zu verwenden, aber nur wenn diese noch innerhalb des rechnerisch möglichen Baudratenfensters liegt.
      Wurde keine serielle Schnittstelle angegeben, geht der Datenstrom in eine Datei im Ordner transmissions, versehen mit einem einzigartigen Dateinamen, der sich aus einem Zeitstempel und dem ursprünglichen Target-Namen zusammensetzt. Mit der Option --transfile="Pfad/Dateiname" können wir den Pfad und den vorderen Namensteil (Präfix) der abzuspeichernden Transmissions-Datei vorgeben. Dateiendung der OWL-Transmissionen ist immer ".owl".


      Serien-Transmission

      Es ist möglich, im Transmissions-Modus mehrere Targets in einem Arbeitsgang anzusprechen. Die Transmissionen werden automatisch als Dateien abgespeichert.
      Voraussetzung ist, dass die Targets systematisch durchnummeriert sind. Dann geben wir im Transmissions-Modus einfach einen Target-Namen mit Platzhaltersymbolen, also "?" oder "*", an, und das Programm sucht alle zu diesem Muster passenden Targets und erzeugt für jedes eine individuelle Transmission.
      Auf diese Weise erzeugte Serien-Transmissionen werden per Default im Ordner transmissions mit einem analog durchnummerierten Dateinamen abgelegt. Beispiel:
      owl --targetname=bootloader0? --flashfile=testprogram.hex
      würde alle Bootloader erfassen, die in der Art "bootloader01" bis "bootloader09" durchnummeriert sind und für jedes einzelne Target eine maßgeschneiderte Transmission erzeugen, die die Firmware "testprogramm.hex" enthält. Die Transmissions-Dateien mit der Endung ".owl" landen per Default im Ordner transmissions.
      Warnung: Dieses Feature ist ausschließlich für Serien-Transmissionen geeignet, die sich auf denselben Controller-Typ beziehen.


      Bootloader-Erzeugung

      Die Software erwartet einen gültigen Device-Namen und holt sich aus dem Ordner Templates die dazugehörige Datei mit den Default-Einstellungen. Dann erzeugt sie aus auf Grundlage dieses Maschinencodes in der weiter oben beschriebenen Weise den individuellen Bootloader und speichert diese Datei zusammen mit Meta-Infos in der sogenannten Target-Datei im Ordner targets ab ab.

      Serien-Bootloader-Erzeugung

      Analog zum Feature "Serien-Transmission" steht natürlich eine Funktion bereit, mit der sich Bootloader in Serie erzeugen lassen. Dazu geben wir einfach ein zusätzliches Argument, nämlich "Number" (Anzahl) an. Die Software generiert dann fortlaufend durchnummerierte Target-Dateien für die gleiche Hardware-Konfiguration aber mit unterschiedlichen Krypto-Schlüsseln.
      Beispiel:
      owl --device=tn2313 --rxport=d0 --txport=d1 --number=10 --targetname=testloader

      erzeugt 10 Targets mit den Dateinamen

      testloader00.hex
      testloader01.hex
      ...
      testloader09.hex

      Diese Loader könnten nun an 10 Zielgeräte verteilt werden. Der Zugriff auf das einzelne Gerät ist aber nur für denjenigen möglich, der die dazu passende Target-Datei besitzt.
      Wegen des Entropie-Problems sollten nicht mehr als etwa 100 Bootloader in einem Durchlauf erzeugt werden. Die Software gibt eine entsprechende Warnung heraus. Es ist aber möglich, in Etappen wesentlich mehr Bootloader zu erzeugen.

      Zufallsschlüssel

      Die OWL-Software setzt bei der Erzeugung von Bootloader-Schlüsseln auf das Zufallsprinzip. Bei einer Schlüsselweite von 128 Bits ist praktisch ausgeschlossen, dass jemals im selben Universum zwei zufällig identische Schlüssel miteinander in Konflikt geraten. Dieser Unwahrscheinlichkeitsdrive macht es möglich, einzigartige Geräteschlüssel lokal zu erzeugen und weltweit zu nutzen, ohne dass diese Schlüssel von irgendeiner zentralen Stelle gespeichert und auf Kollisionen geprüft werden müssten. Das bedeutet Freiheit und Selbstbestimmung für die Nutzer.
      Nebenbei lösen Zufallsschlüssel einige Probleme, die es mit dem passwortbasierten Zugriffsschema á la TSB immer wieder gegeben hat; insbesondere in Hardware-Setups mit mehreren Bootloadern an einer gemeinsamen Programmierleitung. Die OWLs haben von Anfang an individuelle 128-Bit-Schlüssel und sind konfliktfrei adressierbar, egal wie viele es sind. Die Verknüpfung mit einem memorierbaren "Target-Namen" erfolgt über den Dateinamen und kann auch später noch geändert werden. Für den berechtigten (autorisierten) Nutzer ergibt sich ein transparenter Zugriff auf alle selbst erzeugten Bootloader. Für den Herausgeber einer Serie von Bootloadern bleibt ebenfalls alles übersichtlich, da die Target-Namen ja durchaus systematisch (mit Seriennummerierung) erzeugt werden können.
      Für den unberechtigten Angreifer ergibt sich höchstwahrscheinlich rein gar nichts! Das vorliegende Einweg-Konzept antwortet nicht direkt und plaudert somit keine für einen möglichen Angriff verwertbaren Timing-Informationen aus. (Spannender könnte es hinsichtlich möglicher "Seitenkanal-Angriffe" über Power-Analyse und EM-Abstrahlungen werden...)
      Kleiner Wermutstropfen: Die Erzeugung guter Krypto-Schlüssel ist bekanntlich eine Kunst für sich. Wir brauchen vor allem einen brauchbaren Zufallsprozess. Hmm, das Thema hatten wir doch schon einmal...

      Random-Pooling

      Computer können keine Zufallszahlen erzeugen, und den in modernen CPUs integrierten "Zufallsgeneratoren" ist grundsätzlich nicht zu trauen. Für die Erzeugung einzelner kryptografischer Schlüssel sind die üblichen "Hausmittel" (Timerwerte, Mausbewegungen und vielleicht noch eine Prise Entropie aus dem Dateisystem) in der Regel vollkommen ausreichend.
      Sollen aber in kurzer Zeit viele Schlüssel für Bootloader oder IVs für Transmissionen erzeugt werden, dann ziehen diese Methoden nicht mehr. Hier ist es besser, sich einen Vorrat an Entropie anzulegen, einen sogenannten "Random Pool". Dieser wird bei verschiedenen Gelegenheiten mit echter Entropie aufgefrischt, wobei auch durchaus die oben genannten improvisierten Quellen verwendet werden können, aber es können auch weitere Quellen, wie etwa die Entropie aus hochkomprimierten AV-Dateien oder aus einem physikalischen Zufallsgenerator hinzugezogen werden. Wenn die Software dann wieder echte Zufallszahlen benötigt, so kann sie auf den Random Pool zurückgreifen, der sich nicht so schnell erschöpft.
      Die OWL-Software legt einen eigenen Random Pool an. Dazu erzeugt sie im Stammverzeichnis eine Datei randpool.bin. Diese enthält immer mindestens 512 Zufallsbytes, die gewissermaßen "akkumulierte Entropie" beinhalten. Der Zugriff erfolgt nach Art eines Ringpuffers, d.h. die Software liest vom Dateianfang 512 Bytes und kopiert diesen in ihren internen Random Pool in den Arbeitsspeicher. Diesen Block nutzt und modifiziert sie im weiteren Verlauf über aktuelle Timerwerte. Erst beim Verlassen des Programms werden die führenden 512 Bytes vom Dateianfang gelöscht und der modifizierte interne Random Pool wird an das Dateiende angehängt. Somit bleiben immer mindestens 512 Bytes in randpool.bin, die wegen der gelegentlichen Auffrischung mit neuen Zufallsereignissen ein Mindestmaß an Entropie garantieren.
      Dieser Zugriff mag umständlich erscheinen, hat aber einen Grund. Die Datei randpool.bin darf auch größer werden, als 512 Bytes, nämlich bis zu 65536 Bytes (64 KiB). Sie kann mithilfe eines externen Programms und einem physikalischen Zufallsgenerator (TRNG, z.B. XR232USB) mit echter Entropie versorgt werden, und da liegt es nahe, einen größeren Vorrat anzulegen. Wenn nun die OWL-Software auf randpool.bin zugreift, dann rückt der Inhalt der Zufallsdatei in 512-Byte-Schritten immer weiter nach vorne, während erst am hinteren Ende die modifizierten und mutmaßlich etwas schlechteren modifizierten Zufallsdaten angehängt werden. Der Pool wird auf diese Weise also nie wirklich "aufgebraucht", und bevor eine 64k-Zufallsdatei komplett durchgenudelt wurde, kann viel Zeit vergehen, sodass sich der zeitliche Zusammenhang (Korrelation) zwischen Erzeugung und Nutzung der Zufallsdaten komplett verwischt.
      Ein größerer Random Pool ist aber auch nur sinnvoll, wenn die Datei randpool.bin gegen Fremdzugriffe geschützt ist, die OWL-Arbeitsumgebung also nicht ausspioniert werden kann.
      Steht dauerhaft ein TRNG zur Verfügung, ist es sinnvoller, randpool.bin bei jeder Gelegenheit kurz vor der tatsächlichen Nutzung aufzufrischen.
      Als Notbehelf bietet die Software außerdem die Kommandozeilenoption --randpool, mit der wir in bewährter Manie durch hektische Mausbewegungen auf dem Bildschirm einen Grundstock an Entropie erzeugen können.


      Datensicherung

      Die Software erstellt keine automatischen Backup-Kopien. Backups einer kompletten OWL-Installation lassen sich jederzeit mit Bordmitteln anfertigen. Insbesondere der Ordner targets sollte regelmäßig gesichert werden!

      Datensicherheit

      Die Software überschreibt keine Target-Dateien, die bereits existieren. Sollte ein Target-Name bereits vergeben sein, erfolgt eine Warnmeldung und die Operation wird abgebrochen.
      Um das versehentliche Überschreiben von Target-Dateien durch andere Anwendungen zu verhindern, sollten wichtige Target-Dateien zusätzlich mit einem Schreibschutz-Flag versehen werden. Sicherungskopien sind ebenfalls keine schlechte Idee...
      Jede Person, die Zugriff auf den Rechner mit dem OWL-Verzeichnis erhält, ist automatisch "autorisiert" für alles Mögliche. Eine zusätzliche Umschlüsselung, etwa durch ein Master-Passwort, ist nicht vorgesehen. Diese Option wurde bereits getestet und für umständlich befunden.
      Die Arbeitsumgebung, in der auch OWL verwendet wird, sollte für Unbefugte nicht so ohne Weiteres zugänglich sein. Wer sich einem realen Spionage- oder Sabotagerisiko ausgesetzt sieht, wird sich früher oder später ohnehin mit dem Konzept einer gesicherten Umgebung auseinandersetzen. Besser, als Flickschusterei an einzelnen Programmen zu betreiben, ist in jedem Fall: Weitgehende Kontrolle über die verwendete Hardware und Software, Verzicht auf obskuren Müll, geschärftes Bewusstsein für Sicherheitslücken des Betriebssystems, gesamte Arbeitsumgebung auf einer vollverschlüsselten Festplatte usw. Misstraue Regierungen und automatischen Updates! Es muss ja nicht gleich der vom Internet abgeschottete Einzelplatzrechner in einem mit Kupferfolie ausgekleideten Bunker sein...

      Dateiformate

      • Export: Zur plattformübergreifenden Nutzung sind die von der Software neu generierten "Intel-Hex"-Dateien ( Targets) auf 7-Bit-ASCII mit CR-LF-Zeilenvorschüben vereinheitlicht.
        Das OWL-Format für Transmissionen ist ein reines Binärformat. Hier erwarten wir zu Recht, dass diese Dateien problemlos plattformübergreifend genutzt werden können, zumal keine mir bekannte Anwendung bisher mit der Dateiendung ".owl" assoziiert ist.
        Die für den Random Pool verwendete externe Datei randpool.bin ist eine Binärdatei mit 8-Bit-Zufallszahlen, die zwischen 512 und 65536 Bytes lang sein darf.
      • Import: Hex-Dateien mit Datensätzen für EEPROM oder Flash kann das Programm sowohl in LF (Unix), CR (Mac) oder CR-LF (DOS) Formatierung einlesen. Das ist nicht mein Verdienst, sondern der weitsichtigen Umsetzung der entsprechenden I/O-Routinen unter FreeBASIC zu verdanken. Die Software sollte also alle Formate lesen können, die diverse Assembler und Compiler unter dem Oberbegriff "Intel-Hex" auswerfen. (toi-toi-toi...)

      Krypto-Tests

      Die Software bietet drei einfache Test- und Demofunktionen zur Krypto-Schicht.
      Schlüsselgenerator:    owl --key=Hexstring
      Die Angabe eines Hex-Schlüssels ohne weitere Optionen löst den Testmodus für die Schlüsselsequenz aus. Der PRNG wird dann mit dem angegebenen Schlüssel geladen und fortlaufend weitergetaktet. 
      Diese Funktion demonstriert, wie stark sich bereits minimal unterschiedliche Ausgangsschlüssel auf die generierte PRNG-Sequenz auswirken. Sie eignet sich auch gut zum Vergleich mit einer Referenzimplementierung des 128-Bit-SSG-LFSR.
      Die erste Zeile stellt den Startzustand (seed) des PRNG in Hex dar. Die nachfolgenden Zeilen stellen die vom PRNG-Modul ausgegebene Rohsequenz in 4-Bit-Vektoren dar.
      Bei Angabe des Default-Schlüssels (--key="00112233445566778899aabbccddeeff" ) oder eines leeren Arguments (--key="") muss die Bildschirmausgabe der ersten 256 Vektoren wie folgt aussehen (SW:201806xx):

      00112233445566778899AABBCCDDEEFF

      0035F2BFEBBC79D7B6FB6E536D14DCA2
      8A41FABFDFA8A7CB278D9B93ED144009
      4116BBDB07E70257590C1602B2F35DF4
      4C932A9D825C6A464896D1173D8F910C
      1A121048A968625C3513DA716419F961
      9083A7F4853B5D7F2D08C286E12A8008
      08620ECC967578F6AEA63B5FB2B2234F
      0F5CBDE922983F8961C6BF9B65D75082


      Datei-Verschlüsselung:    owl --key=Hexstring --encrypt=Dateiname 
      Verschlüsselt die angegebene Datei mit dem angegebenen Schlüssel nach Standardmethode (eine RST-Sequenz mit IV, Daten, VI). Der Ziel-Dateiname wird durch Anhängen von " .raw" an den ursprünglichen Dateinamen gebildet. Diese Dateiendung erleichtert den Import von gecrypteten Daten in diverse Grafik-, Audio- und Analyse-Tools zwecks weiterer Untersuchungen.

      Datei-Entschlüsselung:     owl --key=Hexstring --decrypt=Dateiname.raw
      Entschlüsselt die angegebene Datei mit dem angegebenen Schlüssel. War die Entschlüsselung erfolgreich (IV=VI), dann wird diese Datei mit einem vorangestellten Zeitstempel unter dem ursprünglichen Namen und wieder mit der ursprünglichen Dateiendung abgespeichert. Die Originaldatei kann also nicht versehentlich überschrieben werden. Originaldatei und wiederhergestellte Originaldatei müssten binär komplett identisch sein. Da die RST-Implementierung für den OWL-Bootloader kein Padding vorsieht, kann es vorkommen, dass die wiederhergestellte Datei bis zu 15 Bytes (Zufallsbytes) länger ist, als das Original. Dieser Effekt tritt in der PC-Variante von RST selbstverständlich nicht auf.
      Wenn die Entschlüsselung fehlgeschlagen ist, speichert die Demofunktion dennoch eine Datei ab, die für Analysezwecke genutzt werden kann.

      Virtuelle Maschinen

      Verschiedene Konstellationen mit VirtualBox 5.xx wurden spaßeshalber getestet, wobei der Gast-Maschine jeweils eine serielle Schnittstelle des Host-Computers per Durchleitung zugeteilt wurde. Alle Kombinationen aus WinXP/Win7/Ubuntu14/Debian8 liefen problemlos. Von der Performance der Schnittstellenanbindung sind keine Wunder zu erwarten. In einigen Fällen machte sich die zusätzliche Abstraktionsschicht deutlich bemerkbar, hier kam der serielle Datenstrom regelmäßig ins "Stottern", aber es gingen keine Zeichen verloren, und ALLE Datenübertragungen an das OWL-Zielgerät waren erfolgreich. Ein "Notfallbetrieb" der OWL-Software in einer VW unter einem anderen Betriebssystem geht also, wenn die Ausgabe eines kontinuierlichem Sendedatenstroms nicht zwingend erforderlich ist.

      To-Do-Liste

      Hardware-Software-Projekte sind bekanntlich eine hochdynamische Kampfsituation. Was hier so schön organisiert rüberkommt, hat sich eher "organisch" entwickelt. Sicher wird auch dieses Projekt wieder die eine oder andere Überarbeitung erfahren und dadurch noch besser werden. Folgende Punkte sind bereits vorgemerkt:
      • Bildschirmausgaben aufräumen / besser formatieren
      • Namen einiger Kommandozeilenoptionen ggf. anpassen
      • Zufallsgeneratorprozess und Random-Pool-Verwaltung weiter verbessern
      • Fehlerbehandlung differenzieren
      • Erweiterungen für > 64K-Devices ausarbeiten und testen
      • Tests mit alternativen Schnittstellen
      • Code aufräumen
      • Bereichsprüfung für zulässige Baudrate
      • Bauerdaustelle Debb-Wokumentation...

      Euer Feedback zählt!


      Nach oben | Index


         

      Hardware-Optionen

      Viele Wege führen nach Flash und EEPROM...

      • Zielplattform mit RS232-Hardware (RS422/RS485, USB-RS232): Das Zielgerät kommuniziert normalerweise über RS232 mit einem anderen Gerät, etwa einem PC oder einem Terminal. Die Schnittstelle kann als klassische RS232, in einer differenziellen Variante wie RS422/RS485 oder über einen USB-COM-Wandler realisiert sein. Aus der Sicht einer Controller-Firmware, die serielle Kommunikation machen will, sind alle diese Varianten sehr ähnlich. Für den One-Way-Loader bedeutet das:

        • OWL kann das vorhandene RS232-Interface nutzen, indem er einfach dieselbe RXD-Leitung benutzt, wie die Applikations-Firmware. Damit sind Firmware-Updates ohne Eingriffe in das Gerät und ohne speziellen Programmieradapter möglich. Das wird allgemein als sehr angenehm empfunden.

        • Der OWL benötigt im Prinzip nur diesen RXD-Port für seinen Datenempfang, da er keine Daten zurücksendet. In manchen Fällen kann es sinnvoll sein, die den TXD-Port ebenfalls zu berücksichtigen, damit der hochohmige Eingang eines MAX232 oder FT232 in Minimalbeschaltung keine unkontrollierten Schwingungen verursacht. Der OWL sendet zwar keine Daten, aber er kann den betreffenden Port als "Dummy-TXD" konfigurieren. Dort wird dann für die Dauer der Bootloader-Sitzung ein statischer High-Pegel (Idle) ausgegeben.

        • RS422/RS485-Leitungstreiber (z. B. SN75176) benötigen zur Datenrichtungsumschaltung ein Hardware-Steuersignal (Transmit-Enable, TE), das softwaremäßig durch die Applikations-Firmware erzeugt werden muss. Der Bootloader sollte dieses Signal ebenfalls erzeugen, damit sichergestellt ist, dass der Leitungstreiber während der Bootloader-Sitzung permanent in Empfangsrichtung geschaltet ist. Auch hierfür kann der OWL seinen TXD-Kanal nutzen. Der wird dann mit einem statischen High oder Low-Pegel belegt, je nachdem, was die Elektronik drumherum so erwartet.

      • Zielplattform OHNE dedizierte RS232-Hardware: Da wird's noch interessanter. Standalone-Anwendungen, die normalerweise nichts mit RS232 am Hut haben, ließen sich bisher nur über vergleichsweise aufwendige Two-Wire- oder One-Wire-Interfaces mit Firmware-Updates versorgen. Der OWL braucht nur noch eine beliebige Portleitung, die durchgängig als Eingang arbeitet. Daraus ergeben sich neue Möglichkeiten:

        • Elektrisch: Wir reservieren auf der Seite des Mikrocontrollers eine beliebige Portleitung und führen diese zusammen mit Masse auf einen zweipoligen Steckverbinder raus. Zur Not kann die Verbindung auch über zwei Klemmprüfspitzen hergestellt werden. Naheliegende Variante, wenn so ein One-Wire-Adapter (CI-V-Interface) ohnehin vorhanden ist.
          Aber es geht noch einfacher. Wir könnten das TXD-Signal von einer echten RS232 (also -12V bis +12V) per Vorwiderstand und Z-Diode auf TTL-Pegel (0V / 5V) zwingen. Die zwei Bauteile lassen sich leicht auf der Controller-Platine oder in fliegender Verdrahtung in einem D-SUB-Stecker unterbringen. Ultrasimple Schaltung!
          [Bild]
          Das Signal ist dann gegenüber der sonst üblichen Logik invertiert. Das macht aber gar nichts. Wir konfigurieren den Bootloader einfach für invertiertes RXD-Signal, und schon stimmt's wieder!

        • Optokoppler: Ein Standard-Optokoppler, wie etwa der PC817, befindet sich auf der Platine des Mikrocontrollers oder auf der Seite der RS232-Schnittstelle bzw. hinter einem FT232. Die Opto-Variante bietet einen perfekten Schutz gegen Spannungsdifferenzen und HF-Einstrahlung.
          Die Sende-LED des Kopplers wird vom TXD-Signal des Computers gesteuert. Der Fototransistor auf der Seite des Controllers zieht dann die RXD-Empfangsleitung gegen Masse. Für verbesserte Flankensteilheit kann ein Pullup-Widerstand von einigen Kiloohm auf der Seite des Porteinganges erforderlich sein. Weitere Bauteile oder Hilfsspannungen werden nicht benötigt. Diese und auch die nachstehende Freiluft-Opto-Variante haben den großen Vorteil, dass wir eine eventuell notwendige Signalinvertierung leicht realisieren können, indem wir die Sende-LED eben andersherum anschließen.

        • Freiluft-Opto: Dabei handelt es sich um einen räumlich aufgetrennten Optokoppler. Auf der Seite des Mikrocontrollers wird die von OWL genutzte Portleitung mit einem Pullup-Widerstand gegen High gezogen und ein Fototransistor zieht diese Leitung auf Low, wenn ausreichend rotes oder infrarotes Licht einstrahlt. Für Opto-Interfaces gibt es interessante Varianten. So sind auch "getarnte" und kostenoptimierte Programmierschnittstellen möglich. Der Datenempfang funktioniert zum Beispiel ganz vorzüglich über den Fototransistor einer gewöhnlichen Gabellichtschranke, da auch diese relativ schnell schalten. Für die Nutzung also OWL-Empfangskanal muss die gegenüberliegende Sende-LED in einem Gabelkoppler natürlich abgeschaltet oder optisch verdunkelt werden. Zur Datenübertragung halten wir dann unser TX-Lichtschwert  dran, resetten den Controller und starten die OWL-Transmission. (Ich hielt das zunächst für eine wackelige Angelegenheit und war dann doch positiv überrascht, wie gut das in den meisten Fällen funktioniert.)






        • Kapazitive/magnetische Koppler: Der kontinuierliche OWL-Datenstrom lässt sich wegen der ausgeglichenen 0/1-Bilanz gleichstromfrei bzw. "floatend" übertragen, ohne dass eine Modulation erforderlich wäre. Die Übertragung über kapazitive oder induktive Eingangsbeschaltungen wurde ansatzweise getestet und funktionierte mit moderaten Geschwindigkeiten. (Wenn es in erster Linie auf die Potenzialtrennung ankommt, wäre eine Lösung mit Optokopplern vorzuziehen!)

        • PC-Audio auf OWL-RXD: Rein experimentell! Das OWL-Signal ist nicht nur gleichspannungsfrei, sondern auch bandbegrenzt, das heißt, es kommen im keine Frequenzen vor, die unterhalb oder oberhalb einer bestimmten Eckfrequenz liegen. Jedenfalls, wenn wir das Rechteck mal ganz unverbindlich mit einem Tiefpass vergewaltigen. Dann "klingt" es wie ein waschechtes "Modem-Signal" und hat auch tatsächlich die wichtigsten Eigenschaften eines solchen. Damit sollte es im Prinzip auch möglich sein, die Transmission über einen hinreichend verzerrungsfreien Audiokanal zu führen, statt über die serielle Schnittstelle. Firmware-Updates können als Sound-Datei verpackt und über Spielzeuggeräte, wie MP3-Player, Smartphones und Tablets an einen Ziel-Controller gesendet werden könnten. Diese haben ja meist keine Standardschnittstellen mehr, können aber praktisch jedes Audioformat abspielen und haben einen Kopfhöreranschluss. Die Herausforderung besteht nun darin, aus dem Audio mit geringem Aufwand wieder ein einigermaßen steiles und phasenrichtiges Rechteck zu machen. DAS schaue ich mir bei Gelegenheit noch einmal genauer an!

      Nach oben | Index



      Anmerkungen

      Kleiner Krypto-Kontest

      Die Wahl eines geeigneten Kryptosystems war die mit Abstand schwierigste Entscheidung des ganzen Projektes. Für AES, XTEA, eine klassische XOR-Stromchiffre und "RST" standen Assembler- UND FreeBasic-Quelltext zur Verfügung oder konnten mit vertretbarem Aufwand erstellt werden. Der Entscheid für RST fiel aufgrund pragmatischer Abwägungen:

      Algorithmus
      AVR-Implementierung
      Vorteile
      Nachteile
      AES
      (Rijndael)
      • Zertifizierbar, weit verbreitet
      • Gute statistische Eigenschaften (Diffusion und Konfusion) 
      • Auf AVR-Mikrocontrollern vergleichsweise schnell
      • Alle Blockchiffre-typischen Key-Feedback-Varianten lassen sich realisieren
      • Weiterer Code für CRC und Key-Feedback erforderlich
      • Enormer Speicherbedarf (Lookup-Tabellen in Flash)
      • Entschlüsselung langsamer als Verschlüsselung
      • Für Bootloader-Anwendung überdimensioniert
      • Für kommerzielle Implementierungen tw. Lizenzerwerb erforderlich
      XTEA
      ("eXtended Tiny Encryption Algorithm")
      • Standard 64-Bit-Blöcke,
        128-Bit-Schlüssel
      • Code: 206 Bytes (Kernfunktion)
      • Takte pro Block: ~ 12.600
        (aufgeteilt auf 2 x 8 Byte)
      • Referenz: www.efton.sk (Link veraltet)
      • Patentfrei und i.d.R. lizenzfrei
      • Nachgewiesen gute statistische Eigenschaften
      • AVR-Assembler-optimierte Version aufgeräumt und kompakt
      • Erheblicher Zusatzaufwand für Key-Feedback und Fehlererkennung
      • Eher schwach bei minimaler Rundenzahl
      • Arbeitet auf 64-Bit-Datenblöcken; Anpassungen für 128-Bit-Key-Chaining erforderlich, könnte Schwachstelle bedeuten
      PRNG-XOR (Stromchiffre)
      • Code: ~60 Bytes
        optimiert für Kernfunktionalität
      • Block-XOR
      • Takte pro Block: < 1000
      • Klassische Stromverschlüsselung
      • Mit kryptografisch abgehärtetem PRNG für viele Zwecke ausreichend
      • Sehr kompakte Lösung
      • Erheblicher Aufwand für Key-Feedback und Fehlererkennung
      • Anfällig für Known-Plaintext-Angriffe!
      • Selbst für Bootloader-Anwendungen zu simpel!
      RST
      ("Randomized Substitution-Transposition")
      • Blockchiffre gesteuert durch eine Stromchiffre , hier:
      • Pseudozufallsgenerator mit 128-Bit-Seed
      • Fortlaufender Schlüsselgenerator
      • Initialisierungsvektoren, Über-Alles-Fehlererkennung
      • Modularer Aufbau: Blockchiffre, PRNG, Key-Feedback
      • Code: ~ 160 Bytes
      • Takte pro Block: < 10.000
        bei Mindestrundenzahl
      • Gute statistische Eigenschaften schon bei Mindestrundenzahl
      • IV und Fehlererkennung
        "all inclusive"
      • Inoffiziell ausführlich erprobt
      • Extrem kompakt auf 8-Bit-CPUs umsetzbar
      • Kyptografisch starker PRNG verwendbar
      • Günstiger Kompromiss zwischen Verschlüsselungsstärke, Codeffizienz und Funktionalität
      • Lückenlos nachvollziehbares Konzept!
      • Nicht "zertifiziert"...
      • Starker PRNG kostet viel Rechenzeit
      • Avalanche über einzelnen Block tw. niedrig (< 20%)
      • IV-VI-Mechanismus verlängert Chiffrat um 2 Blöcke


      Blockverschlüsselung mit und ohne Fehlerfortpflanzung

      (1)
      (2)
      (3)
      (4)




      Klartext unverschlüsselt:
      Bitmap-Grafik 200x200 Pixel, 8-Bit Graustufen,
      40 kByte.
      (Das entspricht 2500 Blöcken à 16 Bytes!)
      Verschlüsselt im unsagbar bescheuerten ECB-Modus. Jeder Block wurde mit demselben Satz an RST-Vektoren verschlüsselt.
      Musterbildung im Chiffrat erkennbar. (Schlecht!)

      Verschlüsselt
      mit fortlaufendem Schlüsselgenerator.
      Keine Musterbildung, starkes Chiffrat.
      Entschlüsselt mit Klartext-Schlüssel-Rückkopplung und einem Übertragungsfehler:
      Nachfolgende Daten komplett unbrauchbar.
      Fehler oder Manipulation sicher erkannt!

      Nach oben | Index


      Bilder

      Universeller TXD-Adapter mit Massebezug
      Wie geil ist das denn?! Toppmoderne LED-Technik wandelt invertiertes und nichtinvertiertes TXD-Signal direkt in eine Sendefrequenz von 480 THz um...

      [Schaltbeispiele]

      OWL Rune Draft jt (CC0)
      Logo-Entwurf "OWL rune rulez"


      Nach oben | Index



      Schnellstartanleitung

      1. Voraussetzungen

        • Hardware-Software-Ausstattung für AVR-Projekte (IDE, Compiler/Assembler, ISP-Brenner, Board) AVR-Controller, der von OWL unterstützt wird, auf Platine mit ISP-Anschluss (oder Zwischenstecker)
        • OWL-Download für Dein Betriebssystem
        • Früher shonmal 'was an der Kommandozeile gemacht...
        • Respekt, aber kein Schiss vor den Fusebits!
        • Mindestens eine reale RS232-Schnittstelle oder USB-COM-Wandler ("COMx", "/dev/ttySx")
        • Hello-World-Testprogramm für diesen Controller, z.B. einfachen LED-Blinker, im Format Intel-Hex (Standard)

          2. PC-Installation der OWL-Software

          Das Download-Paket "owl_xxxxxxxx.zip" einfach an den gewünschten Ort entpacken. Ins Verzeichnis 'owl' gehen und dort ein Konsolenfenster öffnen. Nach Eingabe von owl ohne irgendwelche Optionen müsste die allgemeine Hilfeseite durchscrollen. Wenn das funktioniert, dann geht vermutlich auch alles andere. (Unter Unixen " ./" voranstellen, kennste!)

          Der Anschaulichkeit halber verwende ich in diesen Beispielen mal die Langschreibweisen der Optionen.
          Führende "-" bzw.
          "-- " sind aber nicht zwingend. Eine Liste aller Kurz- und Langschreibweisen liefert die Option: --help.
          3. Maßgeschneiderte OWL-Firmware erzeugen

          Beispiel: ATmega8 in einem klassischen RS232-Setup
          (MAX232, FT232) mit Quarz 8 MHz
          Der Mega8 ist mit einem MAX232 (oder FT232) verbunden. Hier werden die Portleitungen PD0/PD1 als RXD/TXD genutzt
          (vom Hardware-UART vorgegeben) . Die ordnungsgemäße Funktion der RS232-Hardware sollte vorher gestet worden sein. Für eine LED an PB2 steht ein passendes Blinkprogramm zur Verfügung. Am besten, wir testen das Blinkprogramm schon einmal im Vorfeld ohne Bootloader. Testplattform mit funktionierender RS232-Anbindung - check! LED-Blinker - check!

          Jetzt erzeugen wir für diese Hardware unseren ersten OWL-Bootloader. In diesem Beispiel verwendet der OWL ebenfalls PD0 als RXD-Eingang. Die Kommandozeile zur Erzeugung des neuen OWL-Bootloaders lautet dann:

          owl --device=m8 --rxport=d0 --clock=8000 --targetname=testowl_m8

          Das war's auch schon! Die neue OWL-Firmware steht unter  /targets/testowl_m8.hex

          4. Installation OWL-Firmware (Bootloader)

          Wir starten ein ISP-Brennprogramm (z.B. "avrdudess", "extreme burner", "TwinAVR") und übertragen die neue Bootloader-Firmware "testowl_m8.hex" per ISP in den Flash-Speicher des Ziel-Controllers! Vorher bitte den GESAMTEN Flash löschen.

          Anschließend setzen wir die Fusebits, wofür eigentlich jedes Brennprogramm eine entsprechende Funktion anbietet. Schön auf die Zuordnung Extended, Low und High achten, das kann sonst ins Auge gehen. Die wichtigste Einstellung für einen Bootloader ist "Self-Programming" (SPIEN). Das muss aktiviert sein, sonst kann er keine Schreibzugriffe machen. Außerdem sollte immer der Brown-Out-Detektor (BODEN) eingeschaltet sein, damit sich ein sauberes Kaltstartverhalten ergibt (Vermeidung von Flash-Korrumpierung).


          Fuses: SPIEN=0; BOOTSZ=10; BODEN=0; BODLEVEL=0; CKSEL=1111; SUT=11
          Byte-Werte:    Ext: $FF         High: $DD         Low: $7F
          Konkret-kryptisch mit "avrdude" an der Kommandozeile:
          avrdude -U efuse:w:0xff:m -U fuse:w:0x7f:m -U hfuse:w:0xdd:m


          Tipp: Im Web gibts praktische Fusebit-Kalkulatoren, die wesentlich informativer und benutzerfreundlicher ausgeführt sind, als so manche integrierte "Hilfefunktion" von prominenten ISP-Programmiertools.

          Damit wäre unser Bootloader auf dem Chip installiert.

          5. Test-Firmware übertragen

          Für diesen Test sollte sich das Blinkprogramm ledblink_m8.hex im Hauptverzeichnis der OWL-Software befinden. Die Controller-Hardware sei in diesem Beispiel an COM2 angeschlossen. Also, Controller resetten, Kommandozeile "abfeuern":

          owl --targetname=testowl_m8 --flashfile=ledblink_m8.hex --serialport=COM2

          Die Übertragung geht mit Standardgeschwindigkeit von 9600 Baud über "COM2" an den Controller. Nach wenigen Sekunden sollte die LED fröhlich zu blinken anfangen. Na, hat's geklappt? War doch voll easy, oder etwa nicht?!

          Hinweis: Für andere AVRs und LED-Ports muss das Testprogramm angepasst werden.

          Info-Kommandos

          Kurzübersicht zu allen Befehlsoptionen:
          owl --help

          Hilfetext zu einer oder mehreren Optionen (hier: 'flasherase', 'timeout' und 'serialport'):
          owl --help --flasherase --timeout= --serialport=


          Liste aller direkt unterstützte AVR-Modelle:
          owl --supported

          Technische Daten zu einem bestimmtem AVR-Modell einsehen:
          owl --device=Modellname

          Stammdaten zu einem selbst erzeugten Bootloader abrufen
          (Beispiel):
          owl --targetname= testowl_m8



          Nach oben | Index


          Lizenz

          In das Projekt One-Way-Loader sind eine Menge Erfahrung, Tränen und Schweiß und Bier geflossen. Nach langem Vorlauf stelle ich der Weltgemeinschaft dieses Gesamtkunstwerk unter nachstehenden Bedingungen zur Verfügung:

          Programme (Firmware, Software) zum One-Way-Loader unterliegen der MIT-Lizenz
          . Ein entsprechender Vermerk ist in allen Quellcodes enthalten. Alle von mir herausgegebenen Programme zum One-Way-Loader sind außerdem quelloffen. Für Spezialversionen können individuelle Vereinbarungen gelten.

          Dokumentation und Bilder zum One-Way-Loader stehen unter Creative Commons - Universell. Darunter fallen Schaltbeispiele, Grafiken, Diagramme und alle Begleitdokumente, die keinen expliziten Copyright-Hinweis enthalten und nicht automatisch einer anderen Lizenz unterliegen. Sämtliche Logos und Icons zum OWL-Projekt sind Eigenkreationen oder Abwandelungen allgemeinfreier Vorlagen.

          Sie wollen meine Arbeit unterstützen? Verbesserungsvorschläge, Lob, Kritik, Spenden


          Nach oben | Index


          Download

          Nach oben | Index


          Links


          Nach oben | Index


          Erstveröffentlichung: 06/2018 ~ Letzte Änderung: 06/2018