Funktionale Sicherheit

Software sichert Hardware

13. April 2016, 9:39 Uhr | von Martin Süßkraut, Jörg Kaienburg und Prof. Dr. Christof Fetzer

In der Medizintechnik hat die funktionale Sicherheit das Ziel, medizinische Geräte so zu bauen, dass jeder anzunehmende Defekt rechtzeitig erkannt wird: Von einem Defekt darf keine Gefährdung für Patienten ausgehen.

Diesen Artikel anhören

Nicht zuletzt aufgrund der Relevanz für das menschliche Leben wurde mit der Normenreihe EN 60601-X ein regulatives Rahmenwerk geschaffen, das die Sicherheits- und Ergonomieanforderungen an medizinische elektrische Geräte und für medizinische Systeme definiert. In anderen Industriesektoren werden ebenfalls besondere Anforderungen an die Produkte und Systeme gestellt, die über jeweils geltende Industriestandards festgesetzt werden. Beispielsweise definiert die internationale Norm IEC 61508 die Anforderungen an die Entwicklung von elektrischen, elektronischen und programmierbaren Systemen, die eine Sicherheitsfunktion ausführen.

Trotz der Unterschiede zwischen den Industriesektoren und den darin zur Anwendung kommenden Produkten steht eine Frage immer wieder im Raum und muss mit einer hinreichend hohen Zuverlässigkeit beantwortet werden: Kann ein (funktionaler) Defekt eines sicherheitsrelevanten Produktes rechtzeitig erkannt und eine Gefährdung von Personen oder der Umwelt verlässlich verhindert werden?

Im Folgenden wird von einem exemplarischen Medizingerät ausgegangen, das eine sicherheitskritische Funktion ausübt: die Versorgung von Patienten (Medikament, Sauerstoff). Dieses Medizingerät bestehe teilweise aus Consumer-Komponenten, die nicht für sicherheitsgerichtete Medizinanwendungen entwickelt wurden. Es wird gezeigt, dass man trotzdem mit solchen Komponenten funktional sichere Produkte bauen kann. Dazu bedarf es geeigneter Maßnahmen, die Fehlverhalten erkennen und melden.

Beispielhafte Sicherheitsfunktion

Der Fokus liegt auf dem Verfahren "Diversified Encoding". Dabei handelt es sich um ein Erkennungsverfahren, das vollständig in Software umgesetzt und demzufolge komplett unabhängig von der zugrunde liegenden Hardware ist. Es erkennt transiente, permanente und systematische Fehler und erreicht die Erkennungsraten der höchsten Sicherheitsstufen. Die Vorteile dieses Encodings sind:

  • Die originäre Funktion eines damit geschützten Programms wird nicht geändert.
  • Das Verfahren wird automatisiert mit Hilfe eines Entwicklungswerkzeugs in das zu schützende Programm eingebaut.
  • Der Schutz wirkt kontinuierlich während der gesamten Laufzeit verschleißfrei und komplett Hardware-unabhängig.

Insbesondere der zuletzt genannte Vorteil bedeutet, dass Entwicklern der Freiheitsgrad gegeben wird, sogar mit sogenannter COTS-Hardware sicherheitskritische Medizingeräte entwickeln zu können.

Die elementare Sicherheitsfunktion, die als Grundlage für alles Weitere dient, ist ein abgesicherter Zähler - beispielsweise für eine abgegebene Wirkstoffmenge. Die Funktion hat die folgenden vereinfachte Spezifikation:

  • Der Zähler wird durch eine vorzeichenlose 32-bit-Ganzzahl repräsentiert.
  • Der Startwert des Zählers ist 1.
  • Der Zähler hat eine Schnittstelle zum Abfragen und Erhöhen des Zählers um einen vorzeichenlosen Ganzzahlwert.
  • Ausführungsfehler beim Verändern des Zählers müssen aufgedeckt werden.

Der Software-Architekt entwirft eine C-Schnittstelle zu dieser Spezifikation: "uint32_t incSafeCounter (uint32_t incValue)". Die Implementierung enthält keinerlei Maßnahmen, um Ausführungsfehler aufzudecken. Der Quellcode im Kasten "Implementierung 1" zeigt eine mögliche Implementierung des Zählers (mit C99 fest-breiten Ganzzahltypen).

Implementierung 1
/* Standard C99 fest – breiten Ganzzahltypen */
# include <stding .h>
 
/* Sicherheitskritische Zählervariable */
static unit32_t safeCounter = 1;
 
/* Implementierung der Schnittstelle */
unit32_t incSafeCounter ( unit32_t incValue )  {
  safeCounter += incValue;
  return safeCounter;
{

 

Software Coded Processing

Software Coded Processing (SCP) baut auf der Coded-Processing-Technologie von Forin [For89] auf. SCP fügt Informationsredundanz zu einem Software-Programm hinzu, um Ausführungsfehler aufzudecken. Um SCP in eine Software zu integrieren, muss das Programm entweder manuell umgeschrieben werden oder es kann ein automatisiert arbeitendes Code-Transformationswerkzeug genutzt werden. SCP wird auf den gesamten sicherheitskritischen Datenfluss eines Programms angewendet: alle Konstanten, Variablen und Operation müssen codiert werden, um SCP verwenden zu können.

In der Literatur werden verschiedene Codierungen beschrieben [For89, SSF09, SSSF10]. Eine verbreitete Codierung ist die AN-Codierung: Jeder Wert im Programm wird mit einer Konstante A vervielfacht [SSF09]. Werte, die kein Vielfaches von A sind, werden als ungültig gewertet. Mit SCP müssen alle Operationen mit diesen codierten Werten arbeiten. Ein Ausführungsfehler erzeugt ungültig codierte Werte. Ein Beispiel ist die Addition 2 + 3. Codiert man mit A = 7 muss die Berechnung zu 14 + 21 umgeschrieben werden. Ohne einen Ausführungsfehler ist das Ergebnis 35. Ein gültiger Wert, weil er ein Vielfaches von 7 ist. Zwei prinzipielle Möglichkeiten für Ausführungsfehler können das Ergebnis beeinflussen:

  • Einer der beiden Operanden ist bereits ein ungültiger Wert. Dieser ungültiger Wert ist entweder das Resultat eines Bitfehlers im Speicher oder er wurde durch eine fehlerhafte Berechnung erzeugt. Sobald die 14 in eine 13 geändert wird, ist das Ergebnis 34 kein Vielfaches von 7 und somit kein gültiger Wert.
  • Die Additionsoperation selbst wird fehlerhaft ausgeführt. Zum Beispiel kann die Operation zusätzlich 2 zum Ergebnis hinzuaddieren. Dann ist das Ergebnis 37; ebenfalls kein gültiger Wert.

Ein codiertes Programm könnte zur Laufzeit jeden Wert zu jeder Zeit auf Gültigkeit überprüfen. Es ist jedoch vorteilhaft, nur die Ausgaben zu prüfen [SSK15]. Zwischenprüfungen sind nicht nötig, weil Fehler durch den Datenfluss bis zu den Ergebnissen propagieren.

Der Quellcode "Implementierung 2" zeigt das Beispiel aus der ersten Implementierung mit einer vereinfachten AN-Codierung mit A = 7.

Implementierung 2
/* Standard C99 fest – brieten Ganzzhaltypoen */
# include <stdint .h>
 
/* 1 is AN – codiert 7 */
static unit64_t safeCounter = 7 */
 
unit64_t incSafeCounter_encoded ( unit64_t incValue )
{
   safeCounter = add_encoded ( safeCounter , incValue );
   return safeCounter;

 

Die wesentlichen Unterschiede zwischen der originalen, nativen Zählerimplementierung und der codierten Zählerimplementierung sind:

  • Datentypen: Die Datentypen wurden von uint32_t auf uint64_t geändert. SCP benötigt zusätzliche Bits für die Informationsredundanz.
  • Konstanten: Alle Konstanten müssen AN-codiert werden. Im Beispiel ist der Initialisierungswert von safeCounter nun 7.
  • Operationen: Codierte Operationen ersetzen alle nativen Operationen. Codierte Operationen arbeiten ausschließlich auf codierten Werten, während die native Operationen auf nativen Werten arbeiten. Zum Beispiel liefert die Operation add_encoded die codierte Summe ihrer beiden Operanden zurück.

Die Sicherheit der AN-Codierung hängt von der Konstante A ab. Die Größe von A und die Hamming-Distanz der resultierenden Codierung beeinflussen die Sicherheit der AN-Codierung [SSK15].

Diversified Encoding

Diversified Encoding basiert auf zwei unterschiedlichen Ausführungen derselben Sicherheitsfunktion:

  • Native Ausführung: Die native Ausführung entspricht der Ausführung der originalen Sicherheitsfunktion ohne Codierung. Der Quellcode für die originale Sicherheitsfunktion bildet dabei den Quellcode der nativen Ausführung. Die native Ausführung arbeitet auf nativen (originalen) Eingabewerten und dem nativen Zustand. Sie ändert nur den nativen Zustand. Das Ergebnis der nativen Ausführung ist die native Ausgabe.
  • Codierte Ausführung: Die codierte Ausführung basiert auf der codierten Variante der Sicherheitsfunktion. Sie arbeitet auf codierten Eingabewerten und dem codierten Zustand. Das Ergebnis ist die codierte Ausgabe.

Beide Ausführungen sind völlig unabhängige Berechnungen, die jedoch mit den selben Werten operieren. Die codierten Eingabewerte sind die codierten Varianten der nativen Eingabewerte. Der Quellcode der nativen Sicherheitsfunktion wird verwendet, um den Quellcode der codierten Ausführung zu erstellen. Die Erstellung kann entweder manuell oder - empfohlen für die Reproduzierbarkeit - mit einem Werkzeug erfolgen.

Das "Diversity Framework" verwaltet beide Ausführungen. Das Code-Transformationswerkzeug erzeugt auch den Quellcode des Diversity Framework aus dem Quellcode der originalen Sicherheitsfunktion.Die Komponente, die die Sicherheitsfunktion aufruft, erkennt und behandelt Ausführungsfehler mit der Hilfe von Checksummen. Ohne Beschränkung der Allgemeinheit wird eine solche Komponente "Aufrufer" genannt. Das Diversity Framework erzeugt zwei Checksummen: eine über die nativen Ausgabewerte und eine über die codierten Ausgabewerte. Die Aufrufer-Komponente arbeitet ausschließlich mit den nativen Ein- und Ausgaben. Nachdem die Sicherheitsfunktion ausgeführt wurde, muss die Aufrufer-Komponente die Checksumme über die nativen Ausgaben mit der Checksumme über die codierten Ausgaben vergleichen. Sind die Checksummen verschieden, wurde ein Ausführungsfehler aufgedeckt, der behandelt werden muss.

Bild: Datenflussmodell von Diversified Encoding
Bild: Datenflussmodell von Diversified Encoding
© Silistra

Der Quellcode für die Schritte (1), (2) und (4) kann von einem Code-Transformationswerkzeug automatisch generiert werden (Bild).

Schritte (1) und (4) sind Teil des Diversity Framework und Schritt (2) ist die codierte Sicherheitsfunktion. Der Quellcode von Schritt (3) ist der originale Quellcode der nativen Sicherheitsfunktion. Die Sicherheitsargumentation für Diversified Encoding baut auf den zwei zueinander diversitären Ausführungen der Sicherheitsfunktion auf [SSK15].

Zähler mit Diversified Encoding

Das Code-Transformationswerkzeug generiert einen Einstiegspunkt - die C-Funktion "incSafeCounterSafe" für die C-Funktion "incSafeCounter". Dieser Einstiegspunkt ist Teil des generierten Diversity Framework für den Zähler und enthält die vier Schritte aus dem Bild:

  1. Die Generierung der codierten Eingabewerte aus den nativen Eingabewerten.
  2. Die Ausführung der codierten Sicherheitsfunktion.
  3. Die Ausführung der nativen Sicherheitsfunktion.
  4. Die Berechnung der Checksumme über die codierten Ausgaben.

Der neue Einstiegspunkt hat die Schnittstelle "uint32_t incSafeCounter Safe(uint32_t* checksum, uint32_t inc Value)". Der Rückgabewert und der Parameter "incValue" haben dieselbe Semantik wie in der Implementierung von "incSafeCounter". Die Aufrufer-Komponente muss einen Zeiger auf eine Variable zum Speichern der Ausgabechecksumme zur Verfügung stellen. Im Folgenden ist immer die Ausgabechecksumme gemeint, falls von der Checksumme gesprochen wird. Einstiegspunkt "incSafeCounterSafe" speichert diese Checksumme unter der Adresse, auf die "checksum" zeigt.

Um die Ausführung auf Ausführungsfehler zu überprüfen, z. B. wenn der Rückgabewert von "incSafeCounterSafe" verwendet werden soll, muss die Aufrufer-Komponente den Wert der berechneten Checksumme mit der Checksumme über die nativen Ausgaben vergleichen. Das Code-Transformationswerkzeug erzeugt für die Berechnung der Checksumme über die nativen Ausgaben die Funktion "uint32_t SIListra_diversity_output_checksum(uint32_t returnValue)".

Das Argument "returnValue" muss der Rückgabewert sein, den "incSafeCounterSafe" zurückgegeben hat.

Code-Transformation

Das Code-Transformationswerkzeug generiert automatisch den Quellcode der codierten Sicherheitsfunktion und des Diversity Framework. Die automatische Generierung hat die folgenden Vorteile verglichen mit einer manuellen Implementierung:

  • Entwicklungszeit: Änderungen am Quellcode der nativen Sicherheitsfunktion können zügig und ohne manuelle Schritte in die codierte Sicherheitsfunktion und das Diversity Framework übernommen werden.
  • Flexibilität: Anforderungen und Transformationseinstellungen können flexibel geändert werden und erfordern lediglich eine erneute Ausführung des Code-Transformationswerkzeugs. Ohne Werkzeugsupport können Änderungen die komplette manuelle Neuerstellung von großen Teilen der codierten Sicherheitsfunktion und des Diversity Framework erfordern: z. B. beim Ein- oder Ausschalten der Kontrollflussüberprüfungen oder einer Änderung am Codierungsparameter A.
  • Korrektheit und Reproduzierbarkeit: Ein Code-Transformationswerkzeug ist nicht so fehleranfällig wie ein Mensch. Diversified Encoding reduziert zusätzlich das Risiko eines Fehlers des Code-Transformationswerkzeugs. Für den Fall, dass sich die vom Code-Transformationswerkzeug erstellte codierte Sicherheitsfunktion nicht so verhält wie die originale Sicherheitsfunktion, wird dieser Fehler als Ausführungsfehler aufgedeckt.

Das Code-Transformationswerkzeug arbeitet wie ein C-Compiler. Es führt die folgenden Schritte in der gegebenen Reihenfolge durch:

  • Vorverarbeitung (durch C-Präprozessor): Das Werkzeug muss den Quellcode aller eingebunden Header-Dateien verarbeiten. Hierfür müssen dieselben C-Makros wie für den Compileraufruf definiert werden.
  • Parsen: Das Werkzeug erzeugt einen abstrakten Syntaxbaum vom vorverarbeiteten Quellcode und führt dabei eine semantische Analyse durch. Beispielsweise wird eine Typanalyse benötigt, um jeder Variablen und jedem Ausdruck einen Datentypen gemäß der Regel des C-Standards zuweisen zu können. Zu diesem Zeitpunkt kann das Werkzeug auch die Benutzung nicht-unterstützter C-Sprachmerkmale erkennen und melden.
  • Codierung: Nach dem Parsen liegen ausreichend semantische Informationen vor, um die Codierung durchzuführen. Das Werkzeug ersetzt alle Konstanten, Variablen und Operationen mit ihren jeweiligen codierten Varianten.
  • Code-Generierung: Die Codierung liefert ein Zwischenergebnis. Als letzter Schritt wird aus diesem Zwischenergebnis wieder C-Code erzeugt.

Der aktuelle Stand der Technik erlaubt die Codierung von fast allen Merkmalen des C99-Sprachstandards. So wird jede Ganzzahlarithmetik inklusive bit-weiser logischer Operationen und Vergleiche unterstützt, ebenso alle Kontrollflussanweisung von C99, d. h. if-else, inklusive Schleifen, Funktionsaufrufe, switch, break und continue. Der indirekte Kontrollfluss sowie setjmp und longjmp werden gegenwärtig noch nicht unterstützt. Darüber hinaus finden auch komplexe Datenstrukturen basierend auf Feldern (Arrays) und structs und Zeigerarithmetik Unterstützung.

Codierung trotzt Optimierungen

Für jede native C-Übersetzungseinheit, die das Werkzeug als Eingabe erhält, erzeugt es eine codierte Übersetzungseinheit als C-Code. Der generierte C-Code muss durch einen C-Compiler weiter verarbeitet werden. Optimierungen im C-Compiler können die Codierung nicht entfernen.

Der Fakt, dass alle Werte Vielfache eines Codierungsparameters A sind, ist für den C-Compiler nicht ableitbar, weil der C-Compiler jede Übersetzungseinheit individuell behandelt. Selbst mit Optimierungen im Linker (Link-Time-Optimizations), welche dem Optimierer alle Übersetzungseinheiten auf einmal sichtbar machen, können die Codierung nicht entfernen.

Umfang der Fehleraufdeckung

Diversified Encoding bietet eine sehr hohe Wahrscheinlichkeit Ausführungsfehler aufzudecken. Die Sicherheit der Lösung basiert auf Software Coded Processing. In Bezug auf IEC 61508 und ISO 26262 haben Experimente und Analysen gezeigt, dass Diversified Encoding eine ausreichend hohe Safe-Failure-Fraction für den höchsten Diagnosedeckungsgrad erreichen kann, was eine Voraussetzung für die höchsten Sicherheitslevel der Normen ist. Beispielsweise beschreibt [GKSF15] ein Fehlerinjektionsexperiment, bei dem die gemessene Wahrscheinlichkeit, dass Diversified Encoding einen injizierten Fehler nicht aufdeckt, bei nur 0,002 % liegt. Für dieses Experiment wurden über 300 Millionen Fehler injiziert.

Diversified Encoding umfasst die Aufdeckung von Ausführungsfehlern in allen Berechnungen einer Sicherheitsfunktion, d. h. im Datenfluss und Zustand 5 der Sicherheitsfunktion.

Eingaben und Ausgaben können mit den Lösungen aus [SSK15] abgesichert werden. Fehler im Zeitverhalten, z. B. zu langsame Ausführung oder ein Absturz der Sicherheitsfunktion, deckt Diversified Encoding in Zusammenarbeit mit einem Watchdog auf (siehe [SSK15]).

Systematische Software-Fehler, d. h. Software-Bugs, werden von Diversified Encoding nicht aufgedeckt. Die für die Aufdeckung solcher Software-Fehler benötigten Informationen - vor allem die Spezifikation - fließen nicht in das Diversified Encoding ein.

Direkte Hardware-Zugriffe, z. B. über Assemblercode, sind außerhalb des Umfangs eines automatischen Code-Transformationswerkzeugs. Es ist aber möglich, Assemblercode manuell zu codieren. In solchen Fällen ist es sinnvoll, automatische Code-Transformation und manuelle Codierung zu kombinieren.

Wozu Diversified Encoding?

Die Entscheidung, Diversified Encoding für die Aufdeckung von Ausführungsfehlern einzusetzen, ist eine Design-Entscheidung, die sicherheitskritische Teile der Architektur und den Entwicklungsprozess betrifft. Für das beste Ergebnis sollte Diversified Encoding so früh wie möglich im Entwicklungsprozess eingeplant werden.

Das Verfahren ist Hardware-unabhängig und macht keine Annahmen über die zugrunde liegende Hardware. Die einzige Anforderung ist die Verfügbarkeit eines Standard-konformen C-Compilers für die Zielhardware. Die Zielhardware selbst muss nicht zertifiziert oder speziell für sicherheitskritische Systeme entwickelt worden sein. Somit ist es möglich, mit Consumer-Hardware und Diversified Encoding sicherheitskritische Systeme zu entwickeln.

Weil es sich um eine Software-Lösung handelt, ist sie flexibler als Hardware-Lösungen. Der Einsatz von Diversified Encoding kann sich auf die sicherheitskritischen Teile eines Systems beschränken und stellt keinerlei Anforderungen an die nicht-sicherheitskritischen Teile. Ein Code-Transformationswerkzeug erhöht die Flexibilität und setzt Entwicklerressourcen für die Entwicklung der eigentlichen Funktion der Anwendung frei. Software Coded Processing ist die Basis von Diversified Encoding. Es ist möglich, Software Coded Processing ohne Diversified Encoding zu nutzen. Allerdings hat Diversified Encoding zwei entscheidende Vorteile gegenüber dem alleinigen Einsatz von Software Coded Processing:

  • Diversified Encoding mit AN-Codierung deckt Fehler auf, die nur von komplexeren Codierungen, wie ANB und ANBD alleine aufgedeckt werden können [SSSF10]. Wegen ihrer Komplexität stellen ANB und ANBD höhere Leistungsanforderungen an die Hardware als Diversified Encoding mit der AN-Codierung. Somit benötigt - bei vergleichbarer Sicherheit - Diversified Encoding weniger Hardware-Ressourcen als Software Coded Processing.
  • Diversified Encoding deckt Fehler des Code-Transformationswerkzeugs auf. Wegen des Vergleiches der originalen Ausführung mit der automatisch generierten Ausführung werden Generierungsfehler des Code-Transformationswerkzeugs aufgedeckt. Somit hat ein Code-Transformationswerkzeug für Diversified Encoding eine geringere Kritikalität als ein Compiler.

Besonders dann, wenn ein Code-Transformationswerkzeug verwendet wird, reduziert Diversified Encoding den Entwicklungsaufwand für das Gesamtsystem. Zusätzlich macht Diversified Encoding durch die kontinuierliche Überwachung der Berechnung regelmäßige Speicherprüfungen und Befehlssatztests zur Laufzeit überflüssig. Die inverse Ablage von Größen innerhalb des Zustandes der Sicherheitsfunktion ist nicht mehr notwendig. Durch die Vermeidung solcher defensiver Entwicklungsmaßnahmen werden infolge Diversified Encoding weniger Entwicklungsressourcen benötigt.
Diversified Encoding mit Software Coded Processing erlaubt so die Entwicklung neuer Generationen sicherheitskritischer Systeme.

Über die Autoren:

Martin Süsskraut ist verantwortlich für Technology and Science, Jörg Kaienburg zuständig für Management and Organization, beide bei Silistra Systems. Prof. Dr. Christof Fetzer ist Lehrstuhlinhaber Systems Engineering an der TU Dresden.

Literatur

[For89] P. Forin. Vital coded microprocessor principles and application for various transit systems. In IFA-GCCT, pages 79–84, Sept 1989.

[GKSF15] Majdi Ghadhab, Jörg Kaienburg, Martin Süßkraut, and Christof Fetzer. Is Software Coded Processing an Answer to the Execution Integrity Challenge of Current and Future Automotive Software-Intensive Applications? In Proceedings of AMAA 2015, 19th International Conference on Advanced Microsystems for Automotive Applications, July 2015.

[SSF09] Ute Schiffel, Martin Süßkraut, and Christof Fetzer. An-encoding compiler: Building safety-critical systems with commodity hardware. In SAFECOMP ’09: Proceedings of the 28th International Conference on Computer Safety, Reliability, and Security, pages 283–296, Berlin, Heidelberg, 2009. Springer-Verlag.

[SSK15] Martin Süßkraut, André Schmitt, and Jörg Kaienburg. Safe Program Execution with Diversified Encoding. In Proceedings of the 13th embedded world conference 2015, February 2015.

[SSSF10] Ute Schiffel, André Schmitt, Martin Süßkraut, and Christof Fetzer. ANB and ANBDmem-Encoding: Detecting Hardware Errors in Software. In Erwin Schoitsch, editor, Computer Safety, Reliability, and Security, volume 6351 of Lecture Notes in Computer Science, pages 169–182. Springer Berlin / Heidelberg, 2010.

 


Lesen Sie mehr zum Thema


Jetzt kostenfreie Newsletter bestellen!

Weitere Artikel zu TU Dresden

Weitere Artikel zu Medizinelektronik