Mikrocontroller sind klein und preiswert. Security-Lösungen haben den Ruf, beides nicht zu sein. In Anbetracht der immer strengeren Vorschriften und Gesetze ist es von entscheidender Bedeutung, ein Gleichgewicht zwischen diesen beiden Aspekten herzustellen.
Mikrocontroller (MCUs) haben seit ihren Anfängen einen gewaltigen Entwicklungssprung gemacht. Mit 4-Bit-Daten und Assembler-Befehlen, die auf einer Handvoll Seiten im Datenblatt des Bausteins ausführlich beschrieben wurden, war die fortschrittlichste Peripherie ein A/D-Wandler. Und externe Kommunikation musste über I/O-Pins erfolgen. Die heutigen 32-Bit-MCUs mit Megabytes internem Programmspeicher unterstützen nicht nur zahlreiche Kommunikationsschnittstellen, sondern von ihnen wird auch erwartet, dass sie diese Schnittstellen nutzen, um High-End-Lösungen wie künstliche Intelligenz und maschinelles Lernen zu realisieren.
Security war bei 4-Bit-MCUs kein großes Thema. In der Regel erfüllten sie eine kleinere Aufgabe in einem größeren System, und mit Code in einem verschlüsselten ROM oder PROM war es nicht möglich, diesen Code zu ändern. Heute ist die MCU jedoch ein integraler Bestandteil des Systems und übernimmt oft so viele Aufgaben, dass ein Betriebssystem erforderlich ist. Dadurch verschwimmt die Grenze zwischen einem Mikrocontroller und einem Mikroprozessor. Doch mit großer Leistung geht auch große Verantwortung einher. Es liegt nun in der Verantwortung des Mikrocontrollers, für die Security des Gesamtprodukts zu sorgen.
Starke Security erfordert ein starkes Fundament. Bevor die MCU das gesamte System sichern kann, muss sie sich selbst sichern. Es ist zwar wichtig, das relevante Bedrohungsmodell und die Security-Richtlinien für ein bestimmtes Produkt zu bestimmen, allerdings sind einige Security-Lösungen sehr breit einsetzbar. Im Folgenden wird gezeigt, welche Fragen zu stellen sind, um herauszufinden, welche Lösungen für die eigene Anwendung geeignet sein könnten. Wie bei jeder guten Firmware-Implementierung gilt auch hier, von der Basis aus nach oben zu arbeiten.
Alles beginnt mit der sicheren Werksprogrammierung
Lange bevor ein Produkt von einem Endkunden verwendet wird, ist es anfällig für Angriffe. Leider werden diese Bedrohungen von den Entwicklern, die das Produkt entwerfen, in der Regel nicht berücksichtigt. Dies liegt zum Teil daran, dass sie den Produktionsprozess nicht kennen, aber auch daran, dass sie sich mehr auf die Endanwendung konzentrieren, oft mit dem zusätzlichen Druck, einen frühen Prototyp bereitstellen zu müssen.
Sichere Lösungen für die Werksprogrammierung bieten Schutz vor diesen Bedrohungen. Wie Bild 1 zeigt, sind die stärksten Lösungen diejenigen, bei denen der Binärcode mit einer Methode verschlüsselt wird, die nur von einer echten MCU unterstützt wird. Dabei wird der Binärcode auf der MCU selbst entschlüsselt, so dass nur verschlüsselte Daten über die Programmierpins übertragen werden. Viele dieser Lösungen erfordern die Verwendung von MCUs, die mit einem speziellen Bootloader vorprogrammiert wurden. Einige MCUs unterstützen diese Fähigkeit jedoch inzwischen auch in unprogrammierten Chips. Der Vorteil der letzteren Lösung besteht darin, dass weder zusätzliche Hardware oder komplizierte Infrastruktur zum Übertragen der Entschlüsselungsschlüssel noch spezielle Programmiertools sowie auch keine vorprogrammierten MCUs erforderlich sind.
Für MCUs, bei denen diese Funktion nicht integriert ist, bieten erfahrene Programmierdienstleister sichere Lösungen für die werksseitige Programmierung an. Diese Unternehmen bieten Garantien (Zertifizierungen oder anderes), dass die Daten sicher gehandhabt werden. Sie arbeiten dabei mit dem Kunden zusammen, um die erforderliche Hardware, Software und Logistik bereitzustellen.
Die einfachen Dinge zuerst: Deaktivieren externer Schnittstellen
Ein Sicherheitsaspekt, der leicht übersehen werden kann, ist die Deaktivierung der externen Debugging- und Programmierschnittstellen. Bei einfachen Bausteinen, die nach der Inbetriebnahme nie aktualisiert oder debuggt werden, ist dies in der Regel so einfach wie das Ändern eines Bits oder das Auslösen einer Sicherung. Da die MCUs jedoch immer leistungsfähiger werden, ist es daher heutzutage unerlässlich, die Firmware zu aktualisieren und den Debug-Zugriff erneut zu aktivieren. Die Flexibilität, die für die Umsetzung dieser Anforderungen erforderlich ist, verkompliziert den Prozess, um diese externen Schnittstellen zu deaktivieren. Oft sind zusätzliche Schritte oder sogar zusätzliche MCU-Pin-Verbindungen erforderlich. Entwickler sollten sich also vor dem Entwurf ihrer Leiterplatte mit diesem Aspekt der MCU befassen.
Wenn Unbefugte Zugang zu diesen Schnittstellen erhalten, können sie verschiedene Angriffe durchführen:
- Extrahieren des gesamten Codes und der Daten des Bausteins, um das Produkt durch Reverse Engineering zu analysieren oder zu klonen.
- Extrahieren oder Ändern sensibler Informationen, wie z. B. kryptografische Schlüssel und Betriebsparameter des Produkts.
- Vollständige Neuprogrammierung des Bausteins.
Dinge getrennt halten: Isolationsmöglichkeiten
Das Konzept der Isolation ist für Mikrocontroller neu. Da MCU-Code oft von einem kleinen Team oder sogar von einem einzelnen Ingenieur entwickelt wird, mag es sinnlos erscheinen, die MCU vor sich selbst zu schützen! Da Mikrocontroller (MCUs) nun aktiv mit dem Internet verbunden sind und Anwendungen zu einem erheblichen Teil aus Drittanbieter-Code bestehen, muss dieses Schutzniveau berücksichtigt werden. Isolationsmechanismen können auch vor unbeabsichtigten Schäden durch außer Kontrolle geratenen Code schützen und potenziell als Safety-Feature dienen.
Die besten Schutzmechanismen sind hardwareunterstützte Isolation. Memory Protection Units (MPUs) können sehr effektiv sein, haben aber oft Schwachstellen. Proprietäre Mechanismen wie Arm TrustZone schließen viele dieser Sicherheitslücken. Zu beachten ist, wie die Grenzen zwischen den vertrauenswürdigen und den nicht vertrauenswürdigen Bereichen festgelegt werden. Wenn sie in der Software festgelegt sind, kann bösartiger Code sie möglicherweise verändern. Die wirksamsten Lösungen legen diese Grenzen unveränderlich fest. Dies bringt jedoch die potenzielle Herausforderung mit sich, dass Firmware-Updates innerhalb einer bestimmten Größe bleiben müssen.
Secure Bootloader schützt Firmware-Updates
Auch wenn ein Produkt nicht so profiliert wie ein Smartphone ist, können selbst einfache Geräte wie vernetzte Thermostate Hackern Zugang zu einer bestimmten Infrastruktur bieten. Aus diesem Grund haben Security-Konsortien und Regierungen auf der ganzen Welt erkannt, dass Firmware-Updates für vernetzte Geräte zum Schutz vor Security-Bedrohungen möglich sein müssen. Um sicherzustellen, dass diese Möglichkeit nicht noch mehr Probleme mit sich bringt, muss dieses Update auf sichere Weise durchgeführt werden.
Es gibt eine Vielzahl von Möglichkeiten, einen Secure Bootloader zu erstellen. So verlockend es auch sein mag, einen solchen von Grund auf neu zu entwickeln, so ist es doch viel effizienter, ein vertrauenswürdiges Open-Source-Projekt zu nutzen. Viele MCU-Hersteller bieten sogar Portierungen dieser Lösungen in ihren Softwarepaketen an. Diese Lösungen sind für die meisten gängigen Anwendungsfälle konfigurierbar. Da sie quelloffen sind, lassen sie sich an spezielle Anforderungen anpassen. Das Beste an diesen Lösungen ist, dass sie auf den jahrelangen Erfahrungen und dem Know-how der Firmware-Entwickler basieren. Außerdem wird die Implementierung von Security-Experten kontrolliert und überprüft, um sicherzustellen, dass es keine versteckten Hintertüren gibt.
First-Stage-Bootloader ist von Mikroprozessoren inspiriert
Die bereits erwähnte Secure-Bootloader-Lösung fokussiert in der Regel darauf, sicherzustellen, dass nur authentische Firmware-Updates akzeptiert werden. Viele dieser Lösungen bieten auch eine weitere Funktion: die Möglichkeit, den Anwendungscode vor seiner Ausführung zu authentifizieren. Doch wie lässt sich sicherstellen, dass der Secure Bootloader selbst nicht korrumpiert wurde?
Mikroprozessoren lösen dieses Dilemma durch die Verwendung eines First-Stage-Bootloaders. Dabei handelt es sich um ein paar wenige ausführbare Codes, die in das Silizium integriert sind. Sie authentifizieren die Secure-Boot-Lösung der Anwendung, die dann als Second-Stage-Bootloader bezeichnet wird. Bild 2 veranschaulicht den Secure-Boot-Prozess, wenn zudem auch ein Isolationsmechanismus integriert ist. Es ist gut zu wissen, dass diese Bootloader auch als Schutzfunktion dienen können, um sicherzustellen, dass der Code nicht versehentlich beschädigt wurde. Es ist zu beachten, dass die Authentizitätsprüfung des Codes einige Zeit in Anspruch nimmt. Daher sollten alle verfügbaren Optionen geprüft werden, um das beste Ergebnis für das Produkt zu finden.
Sichere Schlüsselaufbewahrung
Ähnlich wie die Sicherung des Zugangs zu einem Gebäude erfordert auch die Sicherung einer Embedded-Anwendung häufig den Einsatz von Schlüsseln. Sie sind zwar kryptografisch und nicht physisch und daher mag das Format anders sein, aber sowohl das Konzept als auch die Folgen eines unvorsichtigen Umgangs damit sind im Grunde identisch. Wenn die Schlüssel verloren gehen, ist der Zugang nicht mehr möglich. Wenn sie in die Hände Unbefugter fallen, haben diese vollständigen Zugang. Wenn jemand die Schlüssel kopiert, kann er erheblichen Schaden anrichten, bevor bemerkt wird, dass etwas nicht in Ordnung ist. Dieses Security-Feature ist so wichtig, dass einige Branchen spezielle Zertifizierungen für den Schlüsselaufbewahrungsmechanismus verlangen.
Es gibt eine Reihe von Möglichkeiten, wie Schlüssel kompromittiert werden können. Wenn ein Angreifer nur Fernzugriff hat, sind Schlüssel, die im Klartext gespeichert oder verwendet werden, anfällig, wenn bösartiger Code eingeschleust werden kann. Wenn ein Angreifer physischen Zugang hat, sind Klartextschlüssel angreifbar, wenn der Schutz der externen Schnittstelle gefährdet wird. Es gibt auch raffiniertere Angriffe, wie z. B. die Analyse der elektromagnetischen Emissionen des Bausteins während eines kryptografischen Vorgangs oder die Messung der Zeit, die für den Abschluss eines kryptografischen Vorgangs benötigt wird. Da diese Angriffe nicht invasiv sind und lediglich Informationen aus dem beobachteten Verhalten ableiten, werden sie als Seitenkanalangriffe bezeichnet. Es gibt auch Angriffe, die durchgeführt werden können, indem die kryptografische Operation zum Scheitern gebracht und die Teilergebnisse analysiert werden. Da diese Angriffe eine Änderung der Betriebsumgebung des Bausteins erfordern, werden sie Fault-Injection-Angriffe genannt. Kryptografische Schlüssel sind eines der kritischsten Elemente einer Security-Lösung und damit ein bevorzugtes Angriffsziel.
DOTF: Schutz von Code und Daten
Im Gegensatz zu Mikroprozessoren befinden sich bei Mikrocontrollern in der Regel der gesamte Code und alle Daten auf dem Chip selbst. Einige Anwendungen erfordern jedoch die Verarbeitungsleistung einer MCU, aber mehr Code oder Daten, als die MCU speichern kann. Die meisten MCUs können serielle Schnittstellen wie SPI oder I2C nutzen, um mit einem externen Flash-Speicher zu interagieren. Dieser kann mit Daten vorprogrammiert werden, die die Anwendung verwenden wird, oder mit Daten programmiert werden, die von der Anwendung generiert werden. Einige MCUs können sogar Code direkt von diesen externen Flash-Speichern ausführen. Nun stellt sich aber ein neuer Security-Aspekt: Wie lässt sich die Vertraulichkeit dieses externen Codes und/oder dieser Daten schützen?
Die „On-the-Fly“-Entschlüsselung ist für das nahtlose Lesen und/oder Ausführen von verschlüsselten externen Daten konzipiert. Es entsteht ein Zeitverlust gegenüber dem Lesen/Ausführen von Klartextdaten/Code. Dieser ist jedoch geringfügig im Vergleich zum „manuellen“ Bestimmen des benötigten Blocks, dem Entschlüsseln in einen temporären Puffer und dem Lesen/Ausführen aus diesem Puffer. Die Anwendungsentwicklung wird ebenfalls vereinfacht, insbesondere im Falle von ausführbarem Code. Der Code wird einfach kompiliert und an der Adresse ausgeführt, an der er im externen Baustein gespeichert ist. Bild 3 zeigt, dass einige On-the-Fly-Entschlüsselungslösungen es ermöglichen, verschiedene Schlüssel für unterschiedliche Bereiche (auch ohne Verschlüsselung) zu verwenden.
Vertrauliche Kommunikation durch sichere Internetverbindung
Als die ersten mit dem Internet verbundenen 8-Bit-Mikrocontroller eine Neuheit waren, machte sich niemand wirklich Gedanken über die Security der Verbindung. Damals waren diese Bausteine einfach kein Ziel für Angriffe, und das Konzept der Exploit-Ketten war weitgehend unbekannt. Viel wichtiger für Entwickler dieser Mikrocontroller-Lösungen war es, dass der IP-Stack ressourcenschonend und effizient war. Das Hinzufügen einer TLS-Schicht (Transport Layer Security) war nicht nur kompliziert, sondern erzeugte auch einen Code, der weder ressourcenschonend und noch effizient war.
Das Gute daran ist, dass die meisten Entwickler inzwischen die Notwendigkeit einer Security-Schicht wie TLS in ihrem Kommunikationspfad verstehen und akzeptieren. Auch die meisten öffentlichen Cloud-Dienste verlangen diese in Form von TLS oder DTLS. Die einzige Frage ist, ob man TLS oder DTLS braucht. Die Antwort hängt vom jeweiligen Kommunikationsprotokoll ab, ob dies TCP- oder UDP-basiert ist. (na)