Leitfaden für die Modellierung von Smartcard Anwendungen mit Borland Together

Größe: px
Ab Seite anzeigen:

Download "Leitfaden für die Modellierung von Smartcard Anwendungen mit Borland Together"

Transkript

1 Leitfaden für die Modellierung von Smartcard Anwendungen mit Borland Together Lehrstuhl für Softwaretechnik und Programmiersprachen WS 2008/ Überblick Dieser Leitfaden erläutert wie man sicherheitskritische Anwendungen, im speziellen Smartcard Anwendungen, mit UML modellieren kann. Zunächst wird kurz auf die verschiedenen UML Diagrammtypen eingegangen. Der Hauptteil erläutert die Verwendung des vorgegebenen UML-Profils, der Sicherheitsdatentypen sowie der Model Extension Language MEL und gibt eine Hilfestellung zur Verwendung der vorgegebenen Projektvorlage im Modellierungstool Borland Together. Für allgemeine Informationen und Tipps zur Modellierung mit UML ist ein Blick in die Unterlagen der Vorlesung Softwaretechnik hilfreich. Dieser Leitfaden geht nur auf die Besonderheiten der Modellierung von Smartcard Anwendungen ein. 2 UML Diagrammtypen Für die Modellierung einer Smartcard Anwendung verwenden wir im wesentlichen drei Diagrammarten: Klassendiagramme für die statische Sicht der Anwendung sowie Sequenz- und Aktivitätsdiagramme zur Modellierung der dynamischen Aspekte. Weiterhin können Use Cases erstellt werden, um Anwendungsszenarien informell darzustellen sowie Deployment Diagramme, um die Struktur der Anwendung, inklusive der Bedrohungen eines Angreifers, zu beschreiben. Für die Aufgabe 4 reicht es aus, wenn Sie Klassen-, Sequenz- und Aktivitätsdiagramme erstellen. Die Modellierung der Anwendung soll unabhängig von technischen Details erfolgen. Dies bedeutet, dass Ihre Modelle z.b. keine Java(Card) spezifischen Datentypen wie byte und short enthalten sollen. Die Beschreibung der Protokolle mithilfe von Aktivitätsdiagrammen soll ebenfalls auf abstrakterer Ebene als die Implementierung erfolgen. Klassendiagramme Klassendiagramme definieren die statische Sicht der Anwendung. Für Smartcard Anwendungen müssen dabei folgende Aspekte berücksichtigt werden: Modellierung der Komponenten der Anwendung: Bei einer Smartcard Anwendung sind die Karte selbst, mindestens ein Terminal sowie evtl. weitere Komponenten zu modellieren. Jede Komponente soll als eigene Klasse definiert werden. Nachrichten: Jeder Nachrichtentyp muss als eigene Klasse definiert werden. Jede dieser Klassen ist abgeleitet von einer abstrakten Klasse Message. 1

2 Nichtkryptographische sowie kryptographische Daten: Diese werden wie gewohnt als eigene Klassen für komplexe Datentypen bzw. als Attribute für primitive Daten modelliert Status: Bei der Ausführung kryptographischer Protokolle ist es oft notwendig, sich den aktuellen Abarbeitungspunkt im Protokoll zu merken. Dies dient dazu, bei Eintreffen einer Nachricht zu wissen, ob dieser Nachrichtentyp zur Zeit verarbeitet werden kann bzw. darf. Die möglichen Zustände einer Komponente werden als Enumerationklasse definiert. Konstanten: Konstanten werden ebenfalls in einer eigenen Klasse definiert. Die Assoziationen im Klassendiagramm sollen gerichtet sein. Geben Sie für das navigierbare Assoziationsende bitte einen Rollennamen und die Multiplizität an. Nicht vorhandene Multiplizitäten werden als 1 interpretiert. Namen für Assoziationen müssen nicht vergeben werden. Sequenzdiagramme Sequenzdiagramme dienen der Entwicklung der kryptographischen Protokolle. Ziel ist es, die Protokolle in mehreren Iterationen zu entwerfen und dabei nur die Kommunikation zwischen den Komponenten zu betrachten. Ergebnis ist also eine sehr abstrakte Beschreibung der Protokolle. Ein Sequenzdiagramm beschreibt den Lauf eines Protokolls. Betrachtet werden nur positive Läufe, d.h. es treten keine Ausnahmen auf und die Kommunikation wird nicht durch einen Angreifer gestört. Trotzdem muss das Protokoll natürlich so entworfen werden, dass es sicher gegen Angriffe ist. Ein Sequenzdiagramm beinhaltet Lifelines für jede Komponente, die am modellierten Protokoll beteiligt ist. Es gibt also eine Lifeline für das Terminal, eine für die Karte und evtl. weitere, wenn weitere Komponenten oder mehrere Instanzen einer Komponente beteiligt sind. Der Name der Lifeline kann beliebig gewählt werden, der Typ muss einer Komponente aus dem Klassendiagramm entsprechen. Die Modellierung eines Users, der mit dem System interagiert und Protokolläufe startet, ist optional. Die Lifeline des Users soll den Namen User haben, ein Typ muss nicht angegeben werden. Die Nachrichten, die zwischen den Komponenten ausgetauscht werden, werden mithilfe von UML Messages modelliert. Jede Message ist mit dem Namen der Nachricht beschriftet. Der Name ergibt sich aus dem Klassendiagramm, d.h. es kann der Name einer Subklasse der abstrakten Klasse Message angegeben werden. Die Nachrichten zwischen dem User und einer Systemkomponente können beliebig benannt werden, die Benennung muss jedoch eindeutig sein. Aktivitätsdiagramme Aktivitätsdiagramme stellen eine Verfeinerung bzw. Konkretisierung der mit Sequenzdiagrammen modellierten Protokolle dar. Die Idee ist, die Protokolle mithilfe der Aktivitätsdiagramme zu vervollständigen und so auch die Verarbeitung der empfangenen Nachrichten, also die eigentlichen Protokollschritte, zu modellieren. Hierfür verwenden Sie bitte die Model Extension Language (MEL), die im Detail in Abschnitt 5 erläutert ist. Natürlich kann es vorkommen, dass Sie beim Erstellen der Aktivitätsdiagramme einen Fehler in den Protokollen finden und somit die Sequenzdiagramme erneut modifizieren müssen. 2

3 Definition der Sicherheitseigenschaften Wie auch in der vorherigen Aufgabe ist ein wichtiger Aspekt die Formulierung der Sicherheitseigenschaften, die Ihre Anwendung erfüllen muss. Erläutern Sie textuell die Sicherheitseigenschaften, die für Ihre Protokolle gelten bzw. gelten sollen. Verwenden Sie zur Erstellung OpenOffice, Word oder Tex. 3 Verwendung der Sicherheitsdatentypen Um kryptographische Daten definieren zu können, haben wir verschiedene Datentypen vordefiniert, die sie in den Modellen verwenden können: Boolean: Primitiver Datentyp für boolesche Werte String: Primitiver Datentyp für Strings Number: Primitiver Datentyp für Zahlen Key: Datentyp für kryptographische Schlüssel. Ein Schlüssel ist entweder symmetrisch (Symmkey) oder asymmetrisch (PubKey und PrivKey). Ein Schlüssel besitzt ein Attribut key, das den eigentlichen Schlüssel enthält. Nonce: Datentyp für Zufallszahlen. Eine Nonce besitzt ein Attribut nonce, das die Zufallszahl speichert. Secret: Datentyp für Daten, die geheim bleiben müssen. Ein Beispiel hierfür sind PIN Nummern oder Passwörter. Ein Geheimnis besitzt ein Attribut secret, das das Geheimnis enthält. HashedData: Datentyp, der gehashte Daten enthält. Das Ergebnis einer hash-operation ist also vom Typ HashedData. Ein HashedData Objekt besitzt ein Attribut hashed, das die gehashten Daten enthält. SignedData: Datentyp, der signierte Daten enthält. Das Ergebnis einer sign-operation ist also vom Typ SignedData. Ein SignedData Objekt besitzt ein Attribut signed, das die signierten Daten enthält. EncData: Datentyp, der verschlüsselte Daten enthält. Das Ergebnis einer encrypt-operation ist also vom Typ EncData. Ein EncData Objekt besitzt ein Attribut encrypted, das die verschlüsselten Daten enthält. Ob die verschlüsselten Daten symmetrisch oder asymmetrisch verschlüsselt wurden ist anhand des Datentyps nicht zu erkennen. Bitte beachten Sie, dass Daten vom Typ HashedData, SignedData und EncData nicht in den Klassendiagrammen vorkommen sollen. Verwenden Sie stattdessen die Stereotypen hashed, signed und encrypted (siehe Abschnitt 4). Die drei Datentypen können jedoch dafür verwendet werden, um lokale Variablen innerhalb der Aktivitätsdiagramme zu deklarieren (siehe Abschnitt 5). 3

4 4 Verwendung des UML Profils SecureMDD Die UML definiert verschiedene Diagrammtypen, mit denen sich ein System aus unterschiedlichen Sichten beschreiben lässt. UML ist jedoch unabhängig von einer speziellen Domäne und beschreibt nur die Standardkomponenten eines Systems. Um domänenspezifische Besonderheiten mit der UML darstellen zu können, gibt es u.a. die Möglichkeit UML Profile zu definieren. Diese sind leichtgewichtige Erweiterungen der UML. Ein UML Profil besteht aus einer Menge von Stereotypen, Tagged Values sowie Constraints, mit denen sich UML Metamodellelemente in ihrer Bedeutung einschränken bzw. spezialisieren lassen. Für die Modellierung von Smartcard Anwendungen haben wir eine Reihe von Stereotypen definiert, die Sie für die Modellierung der statischen Teile des Systems verwenden können: Smartcard, Terminal : Diese Stereotypen kennzeichnen die Klassen, die ein Applet bzw. ein Terminal repräsentieren. Message : Dieser Stereotyp markiert Nachrichtenklassen HashData, SignData und PlainData : Diese Stereotypen kennzeichnen Datenklassen, die während des Protokolllaufs gehasht, signiert oder verschlüsselt werden. hashed, signed und encrypted : Diese Stereotypen annotieren Assoziationen. Sie geben an, dass ein Datum gehasht, signiert oder verschlüsselt gespeichert wird. status : Dieser Stereotyp annotiert eine Assoziation. Die zugehörige Assoziation verbindet eine Komponentenklasse wie z.b. Smartcard oder Terminal mit einer Enumerationklasse, die die möglichen Status der Komponente definiert. Der Stereotyp gibt also an, dass diese Assoziation den Status der Klasse darstellt. Constant : Dieser Stereotyp annotiert eine Klasse, die Konstanten definiert. 5 Modellierung mit Aktivitätsdiagrammen und der Model Extension Language (MEL) Verwenden Sie Aktivitätsdiagramme, um die mit Hilfe der Sequenzdiagramme erstellten Protokolle im Detail zu beschreiben. Für jedes Protokoll soll dabei ein eigenes Aktivitätsdiagramm erstellt werden. Ein Protokoll besteht aus mehreren Protokollschritten. Ein Schritt wird immer von einer Komponente durchgeführt und umfasst das Empfangen einer Nachricht, das Verarbeiten dieser Nachricht sowie evtl. dem Senden einer generierten Nachricht an eine andere Komponente. Jeder Kommunikationspartner, der am Protokoll beteiligt ist, ist durch eine Swimlane modelliert. Um zu definieren, welcher Komponente die Swimlane zugeordnet ist, soll der Name der Swimlane dem Namen der Klasse im Klassendiagramm entsprechen, die diese Komponente definiert. Sind mehr als eine Instanz einer Komponente an einem Protokoll beteiligt, können Sie zusätzlich Instanzennamen vergeben. Eine Smartcard, die durch die Klasse Copycard im Klassendiagramm repräsentiert wird, könnte im Aktivitätsdiagramm durch eine Swimlane mit dem Namen c : Copycard modelliert werden. Ein Protokolllauf wird in der Regel von einem Benutzer initiiert. Sie können dies modellieren, indem Sie eine Swimlane mit dem Name User definieren. Zur Vereinfachung können Sie 4

5 die Kommuikation zwischen Benutzer und Terminal auch weglassen und nur die Kommunikation der Komponenten untereinander modellieren. In diesem Fall startet ein Protokolllauf in der Swimlane einer Terminal Komponente. Der Start eines Protokolls wird mithilfe eines InitialNodes modelliert. Das Ende eines Protokolls wird durch einen ActivityFinalNode dargestellt. Modellieren Sie das Senden einer Nachricht mittels einer SendSignalAction. Um zu definieren welche Nachricht gesendet wird, geben Sie bitte den Namen der entsprechenden Messageklasse im Aktivitätsdiagramm an. Schreiben Sie die Daten, die gesendet werden sollen, als Argumente der Nachricht. Hat eine Komponente beispielsweise ein Attribut att vom Typ Number und gibt es eine Nachrichtenklasse Msg mit einem Attribut vom Typ Number, modellieren Sie das Senden des Attributs att als Argument der Klasse Msg als Msg(att). Als Argumente können Sie die Felder der Komponentenklasse sowie die im aktuellen Protokollschritt definierten lokalen Variablen verwenden. Das Empfangen einer Nachricht wird durch eine AcceptEventAction modelliert. Wie beim Senden enthält die Action den Namen der entsprechenden Messageklasse. Die Argumente sind jedoch Namen von lokalen Variablen, in denen die empfangenen Daten gespeichert werden. Diese lokalen Variablen sind bis zum Ende des Protokollschritts verwendbar. Enthält Ihr Diagramm also eine AcceptEventAction mit dem Namen Msg(value), wird für das empfangene Datum eine lokale Variable value deklariert. Diese speichert das Datum att, das im vorherigen Schritt gesendet wurde und ist vom Typ Number. Um Zuweisungen, die Deklaration von lokalen Variablen, das Erzeugen von Objekten oder das Anwenden von (vordefinierten) kryptographischen oder mathematischen Operationen zu modellieren, verwenden Sie Actions. Eine Action kann mehrere Anweisungen enthalten, die mit Semikolon getrennt werden. Verwenden Sie in den Actions folgende Notation: Zuweisung: Die Zuweisung eines Wertes, z.b. 3 an eine Variable var hat die Notation var := 3. Deklaration von lokalen Variablen: Die Variable var vom Typ Number wird durch var : Number deklariert. Um der Variablen initial den Wert 3 zuzuweisen, schreibt man var : Number := 3. Erzeugen von Objekten: Um neue Objekte anzulegen, verwenden Sie die Notation tmp : AuthData := create AuthData(..). tmp ist in diesem Fall eine lokale Variable, AuthData ist ein im Klassendiagramm modelliertes Datenobjekt. Kryptographische Operationen: Hashen von Daten: hash(h): HashData HashedData. h ist vom Typ HashData. Verschlüsseln von Daten: encrypt(k,pd): Key PlainData EncData. k ist entweder ein symmetrischer oder ein öffentlicher Schlüssel. pd ist vom Typ PlainData. Entschlüsseln von Daten: decrypt(k,ed): Key EncData PlainData. k ist ein symmetrischer oder ein privater Schlüssel. 5

6 Signieren von Daten: sign(k,s): PrivKey SignData SignedData. Überprüfen der Signatur: verify(k,sd, s): PubKey SignedData SignData Boolean Generieren von Zufallszahlen: generatenonce(): Nonce. Generiert eine neue, noch nicht verwendete Zufallszahl. Mathematische Operationen: Verwenden Sie für mathematische Operationen Java Syntax, also z.b. a + b oder x++. Schlüsselwort self : Bei Namenskonflikten, etwa bei der Verwendung lokaler Variablen, bedeutet das Schlüsselwort self, das auf ein Feld der aktuellen Komponente zugegriffen wird. Zugriff auf Elemente einer mehrwertigen Assoziation: Verwenden Sie für die Zugriffsoperationen dieselbe Syntax wie sie in der Java Collection API definiert ist. Um bedingte Verzweigungen zu modellieren verwenden Sie Decision Nodes. Ein Decision Node hat eine eingehende und zwei ausgehende Kanten. Die ausgehenden Kanten besitzen jeweils einen guard, der die Bedingung für den entsprechenden Zweig angibt. Dies kann entweder ein boolescher Ausdruck oder das Schlüsselwort else sein. Möchten Sie verschiedene Protokollzweige wieder zusammenführen können Sie MergeNodes verwenden. Bisher haben wir nur den erfolgreichen Ablauf eines Protokolls betrachtet. Es ist natürlich auch notwendig die möglichen auftretenden Fehlerfälle zu betrachten. Sie modellieren das Beenden des Protokolls im Fehlerfall durch einen FlowFinalNode. Um anzugeben welche Exception in diesem Fall geworfen werden soll, annotieren sie den FlowFinalNode mit einem Kommentar, der den Namen der geworfenen Exception enthält. Manchmal ist es sinnvoll, einen kleinen Teil eines Aktivitätsdiagramms separat zu definieren, um diesen Teil mehrfach zu verwenden oder übersichtlichere Diagramme zu erhalten. Sie können hierfür Subdiagramme definieren, auf die Sie referenzieren können, indem Sie den Namen der Subaktivität in eine Action schreiben. Ein Beispiel zur Verwendung des SecureMDD-Profils und der Model Extension Language finden Sie in den Vorlesungsfolien. 6 Verwendung der Projektvorlage Bitte verwenden Sie das leere Together Projekt als Vorlage. In diesem wurde das SecureMDD- Profil bereits importiert und kann ohne weitere Modifikationen verwendet werden. Das Projekt besteht aus vier Paketen. Innerhalb der Pakete ClassDiagrams, SequenceDiagrams und ActivityDiagrams erstellen Sie bitte die entsprechenden Diagramme. Das Paket Security- Datatypes enthält die in Abschnitt 3 vorgestellten Sicherheitsdatentypen. Verwenden Sie diese bitte bei der Erstellung der Klassendiagramme. Sie können in Together ein UML-Element mit einem Stereotyp annotieren, indem Sie mit der rechten Maustaste das Eigenschaftenfeld auswählen und dort den Eintrag Stereotyp füllen. Voraussetzung hierfür ist natürlich, dass für das ausgewählte UML-Element Stereotypen definiert wurden. Um die Projektvorlage in Together zu verwenden, sind folgende Schritte nötig: 6

7 Wenn Sie an Ihrem eigenen Rechner arbeiten: Kopieren Sie das SecureMDD Plugin aus dem SVN libs-verzeichnis (Ordner com.securemdd.securemdd 1.0.0) in das Pluginverzeichnis (Together/eclipse/plugins). Starten Sie Borland Together und geben Sie die Lizenzdatei an (über Help Borland- Licensing). Diese finden Sie ebenfalls im SVN. Die Projektvorlage liegt ebenfalls im SVN. Kopieren Sie das Projekt in Ihr SVN- Verzeichnis. Um es in Together zu verwenden, können Sie es über File Import.. Existing Projects into Workspace in Ihren Workspace kopieren. Dabei kann man auswählen, ob das Projekt kopiert oder nur referenziert werden soll. Sollten Sie nicht auf die Stereotypen des Profils zugreifen können, müssen Sie das Profil SecureMDD über Rechtsklick auf dem Projekt Properties UMLProfile auswählen. 7 Hinweise für die Implementierung der modellierten Anwendung Die hier erläuterte Modellierung einer Smartcard Anwendung beschreibt ein System aus objektorientierter Sicht. JavaCard Applets kommunizieren mit einem Terminal jedoch über Byte Arrays. Auch die kryptographischen Operationen der Crypto und Security API sind auf Byte Arrays definiert. Es gibt zwei Möglichkeiten, die mit UML modellierte Anwendung zu implementieren: 1. Man verwendet im Applet dieselben Datentypen, die im Klassendiagramm definiert werden und programmiert die Karte - soweit JavaCard dies zulässt - objektorientiert. Diese Art der Programmierung hat zur Folge, dass alle Objekte, die verschickt werden sollen oder als Eingabe für kryptographische Operationen dienen, in Byte Arrays kodiert werden müssen. Da JavaCard keinen Mechanismus für die Serialisierung von Objekten zur Verfügung stellt, muss dies von Hand programmiert werden. 2. Man programmiert das Applet basierend auf Byte Arrays, d.h. die Variablen, die in der Modellierung als komplexe Datentypen definiert sind, werden als Byte Arrays realisiert. Die Modifikationen der Objekte in den Aktivitätsdiagrammen werden somit zu Kopieroperationen in der Implementierung. Diese Art der Implementierung hat den Vorteil, dass die Kodierung bzw. Dekodierung der Daten wegfällt, jedoch sind die Programme unübersichtlicher und die Programmierung ist fehleranfälliger. Da die Programmierung der Kodierung und Dekodierung der Objekte sehr fehleranfällig ist und viel Zeit in Anspruch nimmt, implementieren Sie die Anwendung bitte - wie in den bisherigen Aufgaben auch - wie unter 2. beschrieben. Verwenden Sie die in der Modellierung definierten Namen für Variablen, Konstanten und Status. Die im Klassendiagramm modellierten Nachrichten werden zu APDUs, d.h. die Namen der Nachrichten im Diagramm werden zu Instructions. Definieren Sie hierfür die benötigten Konstanten. Attribute vom Typ String werden in der Implementierung zu Byte Arrays, Attribute vom Typ Number werden als byte oder short realisiert. Assoziationen mit Multiplizität größer als 1 realisieren Sie bitte als Arrays. Die in den Aktivitätsdiagrammen definierten Exceptions sollen auch in Ihrer Implementierung geworfen werden. Definieren Sie hierfür entsprechende Konstanten. Beachten 7

8 Sie, dass Speicher für lokale Variablen nur in der Initialisierungsphase bzw. beim Installieren allokiert werden sollte. Ihr Programm sollte daher an dieser Stelle von der Modellierung abweichen und benötigten Speicher im Voraus allokieren. Davon abgesehen sollte Ihr Applet jedoch eine Implementierung der modellierten Anwendung, insbesondere der in den Aktivitätsdiagrammen definierten Protokolle sein. 8