ARM TechCon 2015

Architektur ARMv8-M bringt Hardware-Security in Mikrocontroller

6. November 2015, 9:48 Uhr | Frank Riemenschneider
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 2

Interrupts und Funktionsaufrufe in sicherer und unsicherer Welt

Interrupt-Verarbeitung bei Aufruf eines nicht sicheren Handlers aus sicherem Code.
Bild 4: Interrupt-Verarbeitung bei Aufruf eines nicht sicheren Handlers aus sicherem Code.
© ARM

Ein spannendes Thema ist bei einer Konfiguration mit unsicheren und sicheren Bereichen natürlich die Interrupt-Verarbeitung. Grundsätzlich gibt es vier Möglichkeiten: Unsicherer Code wird durch einen unsicheren Interrupt unterbrochen (d.h. der Interrupt-Handler liegt im unsicheren Bereich), sicherer Code durch einen sicheren Interrupt, unsicherer Code durch einen sicheren Interrupt und sicherer Code durch einen unsicheren Interrupt. Die ersten beiden Varianten sind unkritisch und weisen kurze Latenzzeiten im Bereich heutiger Cortex-M-CPUs auf (diese betragen je nach Modell 12-15 Taktzyklen). Ist der unterbrochene Code unsicher und der Interrupt-Handler im sicheren Bereich, gilt gleiches, allerdings muß der Handler durch Software Vorsorge treffen, dass der unsichere Code keine geheimen Informationen überliefert bekommt – indem er z.B. alle Register vor dem Rücksprung löscht.

Einzig und allein kritisch ist die Unterbrechung von sicherem Code durch einen unsicheren Interrupt. Beispiel: Ein A/D-Wandler meldet den Abschluß einer Wandlung, während gerade Daten im sicheren Bereich verschlüsselt werden. Hier muß verhindert werden, dass diesem in den Registern ggf. geheime Informationen überliefert werden, die ein Hacker auswerten kann. Deswegen geht die Hardware wie in Bild 4 ersichtlich vor: Nachdem die Register auf den sicheren Stack gerettet wurden, werden sie automatisch gelöscht, bevor in den unsicheren Zustand gewechselt wird. Ist der unsichere Interrupt-Handler beendet, werden nach dem Wechsel in den sicheren Zustand die Registerinhalte wieder vom sicheren Stack geladen. Diese Aktivitäten erhöhen die Interrupt-Latenzzeit nach unseren Schätzungen um 8-10 Taktzyklen.

Aufruf einer sicheren Funktion aus unsicherm Code über die "SG"-Instruktion.
Bild 5: Aufruf einer sicheren Funktion aus unsicherm Code über die "SG"-Instruktion.
© ARM

Neben Interrupts kann natürlich auch ein normaler Funktionsaufruf einen Übergang in die sichere Welt erfordern, z.B. für den Wechsel vom nicht-sicheren Handler/Thread-Mode in den sicheren Handler/Thread-Mode. Daher implementierte ARM neben einer sicheren und einer unsicheren Adresse einen dritten Adresstyp, die sogenannte nicht-sichere aber aufrufbare Adresse (NSC für Non-secure callable).

Hierzu wurde eine neue Instruktion mit der Bezeichnung „SG“ (Safe Guard) eingeführt, die zwingend an dem Einsprungpunkt, also der Zieladresse in der sicheren Welt, vorhanden sein muss – andernfalls wird eine Exception ausgelöst. Bild 5 zeigt ein Codebeispiel für den Aufruf einer sicheren Funktion. Der Vorteil dieses Verfahrens ist, dass man existierenden Code in der nicht sicheren Welt nicht verändern muss und es unmöglich ist, interne Funktionen in der sicheren Welt oder sogar Funktionen irgendwo in der Mitte aufzurufen, um das System zu korrumpieren. Über die Rücksprung-Instruktion BXNS lr stellt man zudem sicher, dass zur Zieladresse des Inhalts von Link-Register R13, das die Rücksprungadresse im unsicheren Code enthält, zurückgesprungen wird. Ein Hacker könnte ja versuchen, eine falsche Rücksprungadresse, die in der sicheren Welt liegt, in das Link-Register zu laden, um illegalerweise Code in der sicheren Welt auszuführen. Befindet sich die Rücksprungadresse bei der Instruktion BXNS (NS steht für non secure) nicht in der unsicheren Welt, wird jedoch eine Exception ausgelöst. Um einen solchen Funktionsaufruf zu kompilieren, muss dieser mit dem Attribut NSEntry versehen werden.

Natürlich kann man sich hier die Frage stellen, warum man mit NSC einen dritten Adresstyp vorgesehen hat und nicht einfach schon die SG-Instruktion im sicheren Bereich ausführt. Letztendlich besteht ja jeder Befehl aus Bits im Speicher. Man stelle sich vor, der sichere Code würde Daten beinhalten, die zufällig dem Bitmuster der SG-Instruktion entsprechen. In diesem Fall könnte man diese Daten als Einfallstor für die Codeausführung im sicheren Betriebsmodus verwenden. Wenn man jedoch eine Adresse im sicheren Speicher anspringt (was man ja zwangsläufig tun müsste), wird eine Exception ausgelöst, da sich die SG-Instruktion an einer Adresse des Typs NSC befinden muss. Erst nach ihrer Abarbeitung wird in den sicheren CPU-Betriebsmodus umgeschaltet, in welchem dann Code in sicheren und NSC-Speicherbereichen ausgeführt werden kann. Die Tabelle zeigt die Adresstypen und die Codeausführung in Abhängigkeit des CPU-Status.

    Speicheradresse
  
 Secure Non-Secure callable non secure
CPU-Status Secure Ja Ja Nein
Non secure Nein Nur SG-Befehl Ja

Code kann in Abhängigkeit des CPU-Status nur in bestimmten Speicherbereichen ausgeführt werden.



  1. Architektur ARMv8-M bringt Hardware-Security in Mikrocontroller
  2. TrustZone-Sicherheit für Mikrocontroller
  3. Interrupts und Funktionsaufrufe in sicherer und unsicherer Welt
  4. Was ist mit Multimaster-Architekturen?

Lesen Sie mehr zum Thema


Das könnte Sie auch interessieren

Jetzt kostenfreie Newsletter bestellen!

Weitere Artikel zu ARM Germany GmbH

Weitere Artikel zu Mikrocontroller