Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar Híradástechnikai Tanszék Mérési útmutató a Smart card mérés II (Java Card programozás) című méréshez Infokommunikációs rendszerek biztonsága szakirány Elektronikus kereskedelem biztonsága laboratórium A mérést kidolgozták: Ács Gergely, Bencsáth Boldizsár, Berta István Zsolt oktatas@crysys.hit.bme.hu BME, CrySyS Adatbiztonság Laboratórium 2005. október 3.
Tartalomjegyzék 1. Bevezetés 1 2. Elméleti összefoglaló a Java Card technológia 1 2.1. Miért pont Java?.................................. 1 2.2. Java Card fejlesztés................................. 3 2.3. Java Card programozás.............................. 4 2.4. A szabványos Java Card osztályok........................ 6 2.4.1. A java.lang csomag............................ 6 2.4.2. A javacard.framework csomag...................... 6 2.4.3. A javacard.security csomag...................... 6 2.4.4. A javacardx.crypto csomag....................... 7 2.5. Miben különbözik a Java és a Java Card nyelv?................. 7 2.6. Egy tipikus Java Card applet szerkezete..................... 8 3. Mérési eszközök és használatuk 9 3.1. Chipkártya oldal.................................. 9 3.2. Axalto fejlesztőeszköz............................... 9 3.2.1. Applet feltöltése a kártyára........................ 10 3.2.2. APDU manager............................... 11 3.2.3. Applet kiválasztása............................. 11 3.3. Kriptográfiai Java nyelven............................. 11 3.4. Könyvtárak..................................... 12 4. Feladatok 12 5. Minta beugró kérdések 13 6. Jegyzőkönyv beadása és értékelése 13
1. Bevezetés E mérés során a hallgatók a gyakorlatban is megismerkednek az intelligens kártyák Java Card specifikáció szerinti programozásával. Míg a Smart card mérés I során a hallgatók beállított (perszonalizált) kártyának küldtek utasításokat [11], ezen a mérésen az ő feladatuk a kártya működésének meghatározása is. A mérés során a hallgatók egy egyszerű elektronikus pénztárca alkalmazást fejlesztenek a kártyára, majd ezt látják el különféle funkciókkal. A mérés feltételezi, hogy a hallgatók jártasak a Java programozási nyelvben, ismerik a kriptográfia alapvető fogalmait, és elvégezték a Smart card I mérést, amelyekben megismerkedtek a chipkártyák használatának alapjaival. A mérés az Axalto által biztosított kártyákkal és fejlesztőeszközzel történik. 2. Elméleti összefoglaló a Java Card technológia A chipkártyák biztonságos mikroszámítógépek [11]. Biztonságosak, tehát védik a bennük lévő információt, és számítógépek, tehát az információt nemcsak tárolni képesek, hanem műveleteket is végezhetnek rajtuk. Ahogy minden más számítógépet, a chipkártyákat is lehet programozni. E mérés során e világba adunk betekintést. 2.1. Miért pont Java? Amíg a chipkártyákat pusztán assembly nyelven lehetett programozni, a fejlesztő cégek kiszolgáltatottá váltak a kártyagyártóval szemben, mert minden chipkártya-típusnak különböző assembly nyelve lehet. Ha egy alkalmazást át kell vinni egyik kártyatípusról egy másikra vagy ugyanannak a típusnak egy másik altípusára a teljes alkalmazást át kell írni. Ennek orvoslására született a Java Card specifikáció [1]. A Java Card platformfüggetlenséget hoz a chipkártyák világába, és ezzel védi a fejlesztőket a kártyagyártóktól. Így a fejlesztők kiszolgáltatottsága csökken, hiszen sokkal könnyebben tudnak hardvert váltani, amennyiben szükséges. A chipkártya-technológia folyamatosan változik, így a kártyaváltásnak sok indoka lehet: A hardver-ről kiderül valamilyen hiba Nagyobb memóriájú/teljesítményű hardver szükséges A kártyagyártó megszünteti a hardver forgalmazását A kártyagyártó az árral próbálja zsarolni a fejlesztőket A Java Card olyan nyilvános specifikáció, amelynek több implementációja létezik, működését sokan tanulmányozzák [6], [7]. Így a Java Cardra fejlesztők sokkal kevésbé válnak kiszolgáltatottá a specifikáció tervezőivel szemben. További előnyök: A fejlesztés/tesztelés jelentős része PC-n is elvégezhető. Már meglévő, nem kártyára fejlesztett kódok is átültethetőek Java Cardra. A programozóknak nem kell új nyelvet megtanulni. Az appletek könnyen (akár a kártya kibocsájtása után is) telepíthetőek a kártyákra, így a szoftver piacra kerülésének ideje jelentősen lecsökken. 1
A Java nyelv kártyákon való megjelenésének egyik fő célja tehát a platformfüggetlenség, de számos biztonsági szempont érvényesítését is lehetővé teszi. A Java PC-n sem tartozik a gyors nyelvek közé, a PC-kénél jóval lassabb chipkártyákon szintén lassúnak számít: a Java Card kódnál sokkal gyorsabb, ami a kártya natív kódján fut, vagy amit a hardver támogat. Szerencsére, viszonylag ritka, hogy egy Java Card programban bonyolult algoritmusokat kellene implementálni, a gyakran használt műveleteket pedig általában hardveres gyorsítás támogatja. A kriptográfiai műveletek a kártyán elképzelhetetlenek hardveres támogatás nélkül, a modern kártyák már támogatják a gyakran használt kriptográfiai algoritmusokat (RSA, DES, 3DES, stb.). A kártya hardverfájlkezelésén fut annak operációs rendszere. Az operációs rendszer bizonyos szolgáltatásai kívülről is elérhetőek (pl. titkosítás, fájlkezelés), a funkciók többi részét az appletek használják ki (1. ábra). Az operációs rendszeren futhatnak natív applikációk is, de ezek közül Java Cardok esetében csupán egynek van jelentősége: a Java virtuális gépnek (JVM vagy JCVM). A virtuális gépen számos méretben és funkcióban különböző applet futhat. Elképzelhető, hogy az appletek csupán statikusan egymás mellett élnek, de akár dinamikusan is együttműködhetnek. cardlet elérése oprendszer szolgáltatásának elérése Cardlet1 Cardlet2 -attr: +op1() Java Virtuális Gép a kártya operációs rendszere 1. ábra. Egy Java Card belseje. Minden applet rendelkezik egy ún. AID (applet identifier) azonosítóval, amelynek segítségével hivatkozni lehet rá. Ezen AID hasonló a kártyán elhelyezkedő DF-ek AID-jához, így nem mindig lehet tudni, hogy épp egy alkalmazással, kommunikálunk, vagy egy DF-et választottunk ki [11]. A terminálnak először ki kell választania az appletet, ezt követően küldhet neki APDU-kat. Az applet kiválasztása után a kiválasztott applet kapja meg a kártyának küldött APDU-kat, a Select Applet APDU kivételével. Egy applet a következő APDU-val választható ki: CLA INS P1 P2 LC Adatok 00 A4 04 00 n n hosszú string az applet AID-je A Java Card specifikáció három részből áll [2]: Java Card 2.1 Virtual Machine (JCVM) Specification, amely a Java programozási nyelv, 2
valamint a Java virtuális gép elemeinek egy részhalmazát definiálja a chipkártyákon való haszálathoz. Java Card 2.1 Runtime Environment (JCRE), amely a Java kártyák futás közbeni viselkedését adja meg, vagyis a kártya operációs rendszerének az appletek felé tanúsított viselkedését definiálja. Java Card 2.1 Application Programming Interface (API) Specification, amely a chipkártyás környezetben elérhető szabványos Java osztályokat és csomagokat definiálja (2.4. fejezet). A Java Card specifikáció ma legfrissebb változata a v2.2.1. A mérés során a specifikáció v2.1.1 változatát támogató termékeket fogunk használni. A Java Card mellett a másik nagy specifikáció az intelligens kártyák programozására a MULTOS [9]. 2.2. Java Card fejlesztés forrás file.java Java Compiler Java byte kód.class Converter Cardlet Loader kártya byte kód.cap 2. ábra. Egy Java Card fejlesztés. Hogyan történik egy Java Card fejlesztés (2. ábra)? 1. Elkészítjük a forráskódot. Egy vagy több osztályt hozunk létre, ahol a fő osztály a javacard.framework.applet leszármazottja. 2. A forráskódot lefordítjuk byte kóddá. Egy Java Card program byte kódja ingyenes eszközökkel (pl. JDK) elkészíthető. 3. E bájt kód egy emulátor vagy egy egyszerű JDK segítségével a PC-n tesztelhető. 4. Az appletet konvertálni kell egy a kártyagyártótól származó konvertáló programmal. Ez kiszűri a nem Java Card konform elemeket, és az adott kártyatípus kódjára. 1 konvertálja a programot. Az így képződő fájl gyártófüggő elemeket is tartalmazhat, és átmenetet képezhet a bájt kód és a natív kód között. 1 A Java Card platformon ugyanúgy interpreter fut, mint sima Java esetében. Ugyanakkor ez a kód kicsit más. Kisebb lesz, a felesleges elemek elmaradnak belőle, továbbá a gyártó egyéb optimalizálásokat is végezhet a hatékonyság további növelése érdekében. Például a Schlumberger Cyberflex kártyán a Java Card Virtual Machine utasításai megmaradtak ugyan, de az optimalizálás során átszámozásra kerültek [10, D függelék]. 3
5. E fájl egy az egyben feltölthető a Java kártyára, majd a megfelelő APDU segítségével meg kell hívni az install metódusát, amely egy példányt hoz létre az osztályból. Ezután az applet működőképes kész APDU-k fogadására. Megfigyelhető, hogy az első három lépés teljesen platform- és gyártófüggetlen. 2.3. Java Card programozás A Java Cardok nyelve a Java nyelvre alapul, használja annak platformfüggetlenségét és objektum-orientált szemléletét. A kártyán objektumok foglalnak helyet, minden applet a javacard.framework.applet leszármazottja. A javacard.framework.applet leszármazott objektum egyes metódusai szolgálnak az alkalmazás belépési pontjaként, pont úgy, mint a webes appletek esetében. A Java Card applet működési módja lényegében a következő: miután az applet feltöltésre kerül, a rendszer meghívja annak install metódusát. Az install általában létrehozza az applet egy példányát, s meghívja a register metódust. Futtatáshoz ki kell választani az adott appletet a megfelelő APDU-val, ekkor a rendszer meghívja annak select metódusát. A Java Card appletnek nincs sokféle eseménykezelője, hiszen csak egyféle közönséges esemény történhet vele: a futtatás. Ilyenkor a process(apdu) metódus hívódik meg. Ez megkapja paraméterként a teljes APDU-t, s feldolgozhatja azt. Egy Java Card osztályból feltöltéskor jön létre egy példány. Amikor az appletet kiválasztjuk, majd APDU-t küldünk neki, az egy metódushívásnak felel meg. Az applet információt az attribútumaiban tárolhat. Az applet attribútumai perzisztensek, vagyis értékük megmarad akkor is, ha elvesszük a kártyától a tápfeszültséget. Az alábbiakban felsoroljuk a Java Card appletek néhány fontosabb 2 beépített metódusát, valamint bemutatunk egy példa Java Card forráskódot (3. ábra). install: Statikus metódus, amely az osztály feltöltése után hívódik meg. Tipikus esetben az install a konstruktort hívja meg a megfelelő paraméterekkel, és példányt hoz létre az osztályból. Egyes kártyák esetében az install hívást automatikusan a feltöltőprogram végzi, a Schlumberger Cyberflex Access kártya esetében ezt a fejlesztőnek külön kell megtennie, s így lehetőség van egy osztályhoz több példányt is létrehozni. konstruktor: Az osztály megpéldányosítását végzi a hagyományos objektum-orientált Java szemléletnek megfelelően. register: select: process: Egy javacard.framework.applet leszármazott objektumot regisztráltat be az appletek közé. Tipikus esetben a konstruktor hívja meg. Az applet kiválasztásakor hívódik meg. A fejlesztés során arra használhatjuk, hogy inicializáljunk bizonyos értékeket, mielőtt a külvilágot az applet közelébe engednénk. Például bekapcsolás után nem lesz aktuális applet, ilyenkor az appletet újra ki kell választani a használathoz. A select segítségével detektálhatjuk például, ha valamilyen tranzakció megszakadt. Ez talán a legfontosabb mind közül, hiszen ez az applet eseménykezelője. Kiválasztás után minden hívást a process kaphat, tipikusan a process tartalmazza az applet működő mechanizmusát, logikáját. A process tartalma tipikusan egy hosszú switch-case utasítás [3]. Az encapsulation és az information hiding az objektum-orientált programozás két lényeges gondolata. Az objektumok adatmezőit elrejtjük a külvilág elől, megtiltjuk a közvetlen 2 Teljes listát pl. [3] tartalmaz. 4
3. ábra. Egy tipikus Java Card program felépítése hozzáférést hozzájuk, elérésük, változtatásuk csakis az objektum metódusain, műveletein keresztül lehetséges. A szoftvertervezés ezen gondolatkört elsősorban a könnyű tervezés és az olcsó karbantartás miatt vezette be. Chipkártyák esetében mindez biztonságtechnikai funkciókat is kaphat. Az intelligens kártya ugyanis nem más, mint egy olyan eszköz, amely elrejti az adatokat a külvilág elől, és elérésükhöz bizonyos műveleteket kínál fel, amelyeket a külvilág APDU-k segítségével hívhat meg. Látszik, hogy hasonló gondolatról van szó. Képzeljünk el egy telefonkártyát [4, 2.3.4.]! Tekintsük ezt egy objektumnak. Attribútumának tekinthetjük a rajta lévő egységek számát, melyen két műveletet értelmezhetünk: 1. Egységek számának lekérdezése 2. Egységek számának csökkentése n-nel, amely sikeres vagy sikertelen lehet Látható, hogy nem definiáltunk olyan műveletet, amellyel a kártyán lévő egységek számát növelhetnénk. Így egy esetleges támadó bármilyen jogosultságokhoz jut is, bármilyen kulcsot vagy jelszót szerez is meg, nem tudja a kártyán lévő egységek számát megnövelni. Ezt azzal értük el, hogy nem engedtünk közvetlen teljes hozzáférést az egységek számához, hanem bizonyos műveletekkel elfedtük azt. A műveletek helyes megválasztása azt biztosította, hogy az eredetileg konzisztens állapotban lévő attribútumok értéke csakis érvényes irányba változhat. 5
2.4. A szabványos Java Card osztályok Az alábbiakban rövid leírást adok a Java Card osztályok csomagjairól, főbb osztályairól. Célom a jelentősebb osztályok megnevezése, valamint a Java Card filozófia ismertetése. Hely hiányában nem törekszem teljességre, csupán a megfelelő irodalomra hivatkozom: [8], [1], [2, 3.6. fejezet]. 2.4.1. A java.lang csomag E csomag funkciója teljesen megegyezik a Java java.lang csomagjáéval. Szerepe a megfelelő ősosztályok biztosítása. Definiálja a java.lang.object osztályt, amely minden osztály őse, valamint a Throwable osztályt, melyből az Exception-ök származnak. Definiál aritmetikai kivételt, tömbindexelési kivételt, stb. Fő különbség a java.lang-tól, hogy jóval kevesebb osztály tartozik bele, így az API jóval karcsúbb lehet. 2.4.2. A javacard.framework csomag Ez a Java Card-ok talán legfontosabb csomagja. Benne foglalnak helyet a Java Card programozás legfontosabb osztályai. Applet: Ez minden cardlet főosztályának őse, jelentősége hasonlít a java.applet.appletéhez. Ő adja a cardlet interfészét a külvilág felé (2.3). A programozó közvetlenül ritkán használja, hanem főappletét leszármaztatja belőle (MyApplet, 3. ábra). APDU: Szintén roppant jelentős osztály. Az Applet process metódusa kapja meg paraméterként (3. ábra), majd általában tömbbé alakítja és úgy hivatkozik az egyes mezőire. AID: Applet Identifier A JCRE minden egyes applethez létrehoz egy ilyen objektumot, majd ezt lehet tőle elkérni, ha egy appletre hivatkozni akarunk [1]. OwnerPIN: A PIN kódok nyilvántartására, kezelésére használt applet. Tartalmazza a kódot, azt, hogy hányszor próbálkozhat a felhasználó, és hogy már hányszor rontotta el. Util: Bizonyos műveletek elvégzésére használatos utility-jellegű osztály, statikus metódusokkal. Itt helyezkedik el egy csomó konverziós rutin (pl. 1 db short-ot 2 db byte-tá konvertál), memória/(tömb)másoló rutin, stb. JCSystem: A System-nek megfelelő osztály. Az applet futtatásának irányítása és erőforrásmenedzsment a feladata. Csak statikus metódusokkal rendelkezik. ISO7816: Az előzőekkel ellentétben ez nem osztály, hanem interfész, és konstansokat tartalmaz. Tartalmazza az APDU-k feldolgozásához szükséges konstansokat (pl. hol helyezkedik el benne a P2 bájt), valamint a szabványos visszaadandó státusszavakat (pl. biztonsági hiba stb.) 2.4.3. A javacard.security csomag E csomag számos interfészt és osztályt tartalmaz. Az interfészek az egyes kulcsok, kulcstípusok elérésére szolgálnak, az osztályok pedig az algoritmusokat valósítják meg, generikus módon. KeyBuilder: Kulcsgenerálásra szolgál, ezt a buildkey statikus metódussal végezhetjük el. KeyPair: Egy kulcspár, egy nyilvános és egy titkos kulcs interfészre tartalmaz referenciát. A genkeypair metódussal generálhatunk kulcspárt. 6
MessageDigest: Ez a hash függvények alapja. Absztrakt osztály, a konkrét hash függvényeket leszármazottain keresztül érhetjük el. E leszármazottakat a MessageDigest statikus getinstance metódusával kaphajtuk meg, amely új objektum példányt hoz létre a MessageDigest-leszármazottból. Az egyes hashelendő blokkokat az update metódussal küldhetjük el, az utolsó blokkot viszont a dofinal metódussal kell elküldeni, ez visszaadja a hash értéket is. RandomData: Véletlenszám-generálásra szolgál. Szintén absztrakt osztály, szintén getinstance metódussal kérhetünk tőle konkrét véletlenszám-generátort. (Az egyes kártyák különböző véletlenszám-generálási módszereket tesznek lehetővé.) Signature: Aláírásra szolgál. Szintén absztrakt osztály, szintén getinstance metódussal kérhetünk tőle konkrét aláíró objektumot, miután az algoritmus típusát meghatároztuk. Ezt követően az init metódusával kell kiválasztani a használandó kulcsot. Ezt követően az update (amely egy hash függvénybe gyűjt adatokat, ha szükség van rá) és végül a sign metódusokkal írhatunk alá. 2.4.4. A javacardx.crypto csomag Ez a csomag egyedül a javacardx.crypto.cipher osztályt tartalmazza a specifikáció szerint, amely az összes kódoló algoritmus közös ősét képezi. Lényegében interfészdefiníciót és konstansokat tartalmaz. A Cipher leszármazottai implementálnak néhány interfészt. A Cipher leszármazottaihoz annak statikus getinstance metódusával férhetünk hozzá, amely létrehoz egy új példányt (!) a Cipher-leszármazottból, amennyiben az adott kártya támogatja azt. 2.5. Miben különbözik a Java és a Java Card nyelv? A Java nyelv kifejlesztésének egyik célja beágyazott rendszerekben való alkalmazás, a másik pedig a weblapokon megjelenő programocskák (appletek) készítése volt, amelyek intelligens funkciókat vittek az addig javarészt statikus weblapokba. Ehhez képest gyökeresen más kihívást támasztott a Java Cardok esete. Míg egy Web-böngészőt futtató PC gyors processzorral rendelkezik, amely képes lehet appleteket hatékonyan futtatni, egy chipkártya néhány Mhzen járó 8 bites processzora és néhány kilobyte memóriája merőben más sebességviszonyokat jelentenek. Így a Java Cardok nyelve, bár szintaktikailag Java, valójában sokkal közelebb áll a C-hez [5]. A Java Card programok lefordulnak JDK segítségével, de nem használhatják a teljes Java nyelvet, pusztán annak egy részhalmazát. A legfontosabb különbségek a következők (teljes lista a [1] specifikációban található): Java Card nyelven nem használhatjuk, csak a Java Card beépített osztályait (lásd 2.4. fejezet) és saját osztályainkat. A Java többi beépített osztályát (pl. java.math.biginteger) a kártyán nem tudjuk elérni! A kártyán lévő Java Virtuális Gép nem támogatja a szemétgyűjtést (garbage collection), így ha létrehozunk egy objektumot, azt nem tudjuk elpusztítani. Az applet és az általa létrehozott objektumok élete addig tart, míg az alkalmazást le nem töröljük a kártyáról. A fentiekből ha a program robosztusságát mindenek felettinek tartjuk, ami például egy digitális pénztárca alkalmazásnál igen fontos szempont logikusan adódó kötöttség, hogy a programozó köteles minden objektumot a konstruktorban létrehozni, s így oldja meg azt, hogy a memória el ne fogyjon menet közben. Fontos! Java Card nyelven dinamikus memóriát foglalni csakis az alkalmazás inicializálásakor (konstruktorban, install medódusban stb) szabad. Ez azt 7
jelenti, hogy new utasítást, getinstance-t és factory-jellegű hívásokat csakis ezeken a helyeken szabad végezni. Szintén nem támogatja a Java Card a thread-eket. A program csakis egyetlen szálon futhat. Mint később láthatjuk, ennek biztonsági okai is vannak. A kivételkezelés másképp történik. Míg Java nyelven a kivételt throw new Exception(); paranccsal dobunk, Java Card nyelven ez ISOException.throwIt(0x6900); paranccsal történik. Látható, hogy ez egy statikus metódushívás. A Java Card kivételeket elkapni nem lehet, kivételdobáskor a kártyán futó alkalmazás futása megszakad, a kivételben megadott kétbájtos szó lesz a kártya által visszaadott két állapotbájt. A Java több alaptípusa nem jelenik meg. A Java Card specifikáció a boolean, a bájt, és a short típusokat támogatja. Míg Java nyelven az int egy alaptípus, és az egyes műveletek eredménye automatikusan intté konvertálódik, Java Cardon nem kötelező az int támogatása (a kártyák általában 8-bites processzorán az int megvalósítása igen lassú). Java Cardon kerülni szokás az int használatát, és gyakran kiírják, az explicit konverziót shorttá: short a = 3; short b = 2; short c = (short) (a*b); Nincsen sem karakter, sem string típus. A stringeket Java Cardon bájt-tömbben tárolják. 2.6. Egy tipikus Java Card applet szerkezete Minden Java Card applet a javacard.framework.applet osztály leszármazottja. Az applet egyes örökölt metódusai jelentik a belépési pontokat. Az install metódus az applet példány létrehozásakor kerül meghívásra, tipikus esetben egy példányt hoz létre az appletből. Az applet konstruktora pedig meghívja a register beépített metódust, és ezt követően az applet kiválaszthatóvá válik. Miután behelyezzük a kártyát, ki kell választani az appletet ahhoz, hogy APDU-kat küldhessünk neki. Kiválasztáskor a select metódus kerül meghívásra, itt célszerű olyan helyzetet kialakítani, amely egy frissen behelyezett kártya esetén szükséges. Például, mivel ilyenkor a felhasználó még nem azonosíthatta magát PIN segítségével, a select metódusban szokás a felhasználót az egyes PIN-ek szerint kiléptetni. Ha az appletet már kiválasztottuk, APDU-kat küldhetünk neki. Az elküldött APDU-kat a process metódus kapja meg. A process feladata a beérkezett APDU feldolgozása, és a kért feladat végrehajtása. A process egy javacard.framework.apdu-t kap paraméterként, és legtöbbször tartalmaz egy byte buffer[] = apdu.getbuffer(); utasítást, és ezt követően az APDU-t bájttömbként érheti el. A process megvizsgálja, az APDU milyen utasítást tartalmaz (INS bájt), és eszerint elágazik. switch( buffer[iso7816.offset_ins] ){ // case 0x02:... //... default: ISOException.throwIt (ISO7816.SW_INS_NOT_SUPPORTED); } Az APDU egyes bájtjait a buffer bájttömb egyes pozícióin érhetjük el. E pozíciók indexeit a ISO7816.OFFSET_CLA, ISO7816.OFFSET_INS, ISO7816.OFFSET_P1, ISO7816.OFFSET_P2, ISO7816.OFFSET_LC, ISO7816.OFFSET_LE konstansok tartalmazzák (lásd: [1]). 8
Ha az APDU-hoz bemenő adat tartozik, a byte byteread = (byte)(apdu.setincomingandreceive()); paranccsal érhetjük el azt. Ezt követően az APDU bejövő adatai is elérhetőek, nemcsak a kötelező fejléc. A byteread változó tartalmazza a beérkezett bájtok számát, vagyis ISO7816.OFFSET_CDATA után még byteread db bájt olvasható ki a tömbből. Ha adatokat szeretnénk visszaküldeni (jellemzően annyi bájtnyit, amennyit az APDU LC bájtjában a terminál kért), akkor először jeleznünk kell, hogy kimenő adatot szeretnénk küldeni, majd meg kell mondanunk, hogy mennyit. apdu.setoutgoing(); apdu.setoutgoinglength((byte)amennyitkuldenikell); Ezt követően a buffer tömbbe (amelyet az apdu.getbuffer segítségével kaptunk) pakoljuk bele a küldendő adatokat, majd apdu.sendbytes((short)0, (short)amennyitkuldenikell); 3. Mérési eszközök és használatuk 3.1. Chipkártya oldal A méréshez Axalto Cyberflex e-gate 32k kártyákat használunk, melyeket az Axalto (korábbi nevén Schlumberger) ajánlott fel e mérés céljára. E kártyák Java Card (v2.1.1) kompatibilisek, és képesek 1024 bites RSA műveletek végrehajtására. A kártya koprocesszora támogatja a DES, a 3DES rejtjelező műveleteket és az SHA-1 hash függvényt is. 3.2. Axalto fejlesztőeszköz A mérés során egyszerű Java alkalmazásokat kell írni, de teszteléshez használhatjuk az Axalto/Schlumberger Cyberflex Access SDK 4.4 fejlesztőeszközét is. Az eszköz a: Start / Programs / Schlumberger Smart Cards and Terminals / Cyberflex Access SDK 4.4/ Cyberflex Access Toolkit 4.4 menüponttal indítható, a hozzá tartozó fájlok a Program Files/Schlumberger/Smart Cards and Terminals/Cyberflex Access Kits/v4/ könyvtárban találhatóak. Amint a kártyát behelyezzük az olvasóba, a rendszer jelzi, hogy egy kártyát érzékelt, és megkérdezi, csatlakozzon-e hozzá. Ezt követően a bal oldali fastruktúrában megtalálható lesz a kártya. A kártya tartalmát (a mellette lévő + jel segítségével) megnyitva a rendszer megkérdezi, melyik kulccsal csatlakozzon a kártyához (4. ábra). Vigyázat: Hibás próbálkozásokkal a kártya véglegesen lezárható, használhatatlanná tehető! Használjuk a Select Key gombot, és válasszuk ki benne a Cyberflex Access e-gate 32K kártyához tartozó kulcsot! Ezt követően csatlakozzunk a kártyához az Establish gomb segítségével! Ilyenkor egy 3DES-sel védett biztonságos csatorna épül ki a kártya és a PC között. 4. ábra. A kártyához való csatlakozáskor ki kell választani a Cyberflex Access e-gate 32K kártyához tartozó kulcsot a Select Key menüponttal 9
5. ábra. Program File Generator beállításai 3.2.1. Applet feltöltése a kártyára 1. Írjuk meg a Java Card applet forráskódját! Rakjuk a megírt appletet egy package-be (ami nincs package-ben, azt nem lehet a kártyára feltölteni), pl. hu.crysys.javacardmeres. Ilyenkor az applet első sora package hu.crysys.javacardmeres; kell, hogy legyen, valamint a forráskódnak is egy hu/crysys/javacardmeres könyvtárban kell elhelyezkednie. 2. Fordítsuk le a forráskódot! Fontos! A forráskódot JDK 1.3 segítségével fordítsuk le! A JDK 1.4 más formátumú bájt kódot használ, és az Axalto eszköz Program File Generatora azt nem ismeri fel! 3. Indítsuk el a Schlumberger Cyberflex Access SDK-t! 4. Konvertáljuk a.class fájlt (vagy fájlokat) a konkrét kártya kódjára! Tools / Make Card Applet / Program File Generator Állítsuk be a Program File Generatort az 5. ábrán látható módon. Package name-hez írjuk be a package nevét, ezt követően látjuk az appletünk osztályát a package feletti (hu/ könyvtár feletti) alkönyvtárból. Adjunk az applet osztályának egy szabadon választott AID-t (legalább 6 bájt), és output directorynak adjunk meg egy létező könyvtárat. Ezt követően válasszuk ki az osztályt és Add Applet, majd adjunk meg egy applet 10
AID-t (egyezzen meg az osztály AID elejével, és legyen legalább 5 bájt hosszú). Végül nyomjuk meg a Create gombot, és ha mindent jól csináltunk, egy.ijc fájlt kapunk (azaz a specifikációval ellentétben nem.cap-ot). 5. Helyezzük be a kártyát az olvasóba és csatlakozzunk hozzá Cyberflex Access e-gate 32k kulcs segítségével. A mérés során üres kártyát használunk, tehát a kártyán az Instances fül alatt nincs semmi, a Load Files and Libraries fül alatt pedig 5 db A000-val kezdődő elem szerepel. 6. Kattintsunk a Load Files and Libraries fülön az egér jobb gombjával, majd válasszuk a New menüpontot! A megjelenő ablakban adjuk meg az.ijc fájlt, és a Program File Generatorban megadott osztály AID-ot, majd nyomjuk meg a Create gombot! Ezt követően a Load Files and Libraries fül alatt megjelenik a feltöltött osztály. 7. Hozzunk létre az osztályból egy példányt! Az osztályon kattintsunk az egér jobb gombjával, majd válasszuk a New / Instance menüpontot! Írjuk be az applet AID-jét (a rövidebbik AID tartozik az applethez, a hosszabbik az osztályhoz), paramétert megadni nem szükséges. Meg kell viszont adni a példány méretét, vagyis azt, hogy hány bájt dinamikus memóriát foglalunk le. Sajnos erre a kártya dokumentációja szerint is a próbálgatás a legcélravezetőbb megoldás. A SkeletonApplet applethez 2000 bájt elegendő. Ezt követően az Instances fül alatt megjelenik az applet. Immár az applet kész a használatra! 3.2.2. APDU manager A Smart card mérés II során megismert APDU manager segítségével küldhetünk APDU parancsokat a kártyának, és láthatjuk a kártya válaszát is. Az APDU manager lehetőséget biztosít korábban összeállított APDU-k megjegyzésére és fájlban való tárolására is. 6. ábra. APDU manager a Cyberflex Access SDK 4.4-ben 3.2.3. Applet kiválasztása Mielőtt az appletnek (kártyán futó alkalmazásnak) parancsokat küldenénk, ki kell választani azt. A kiválasztás történhet az APDU managerrel és ott a Select File by AID (avagy Select Application) APDU-val, vagy pedig az Instances fülön jobb gomb, majd Select Application. 3.3. Kriptográfiai Java nyelven A mérés során a Smart card mérés II -ben leírt kriptográfiai műveleteket lehet használni, amennyiben szükség van rá [11]. 11
3.4. Könyvtárak A mérésekhez szükséges segédanyagok, dokumentációk a c:\scmeres_3 könyvtárban helyezkednek el. E könyvtár a következő alkönyvtárakat tartalmazza: lib/: Itt vannak azok a.jar fájlok, amelyek a cyberflex chipkártyás fejlesztésekhez szükségesek lehetnek. A gépre feltelepített PCSC olvasók eléréséhez az slbjiop.jar fájl szükséges, ezt mind fordításhoz, mind futtatáshoz be kell venni a classpath-ba. docs/: Dokumentációk a fejlesztőeszközről, a terminál oldali könyvtárakról, a JDK-ról. A JavaCard API a JavaCard211API.pdf fileban található. util/: segédprogram a 4. feladathoz, gen_response.bat indításával indul a javaframe, amely bytekódját a DESECBNoPad.class file tartalmazza. src/: SkeletonApplet.java file-t tartalmazza. Ezt a kódot kell a mérés során bővíteni a feladatoknak megfelelően. A benne szereplő kommentek hasznos segítséget nyújthatnak! 4. Feladatok A feladatok megoldásához Java Card appleteket kell írni az src/skeletonapplet.java folyamatos bővítésével. Érdemes a javacard.framework.util csomag statikus függvényeit használni tömbök másolására és összehasonlítására idő, hely és hibalehetőségek csökkentése végett. A Java Card appletek tesztelhetőek az Axalto fejlesztőeszköz APDU managerével, de akár Java programmal is a Smart card mérés II -en tanultak szerint. A fejlesztéshez a JCreator LE Java IDE használata javasolt. A jegyzőkönyv tartalmazza az egyes feladatokhoz tartozó releváns kódrészleteket és azok rövid magyarázatát (teljes pontszám csak ekkor kapható)! Ezenkívül a jegyzőkönyvhöz mellékletként csatolni kell a teljes java forráskódot! 1. Fordítsa le a SkeletonApplet.java appletet, töltse fel a kártyára és próbálja ki! (5 pont) 2. Írjon olyan Java Card appletet, amely egy egyszerű pénztárcát tartalmaz! Az applet tároljon egy egyenleget, és legyen lehetőség az egyenleg lekérdezésére, az egyenleg csökkentésére (vásárlásra) és az egyenleg növelésére (pénz feltöltésére). (10 pont) 3. Fejlessze tovább a pénztárca-appletet úgy, hogy a vásárlás és az egyenleg lekérdezés műveleteket PIN kód védje! (A felhasználónak meg kelljen adnia a PIN kódját, különben a kártya utasítsa el e műveleteket!) (Lásd: OwnerPIN osztály.) (10 pont) Megjegyzés: Ne felejtse a pin kód objektum reset metódusát meghívni a select metódusban! 4. Fejlessze tovább a pénztárca-appletet úgy, hogy a pénz feltöltés műveletet szimmetrikus kulcson alapuló kihívás és válasz alapú azonosítás védje! Ha a terminál feltöltés műveletet kezdeményez, a kártya küldjön a terminálnak egy véletlen kihívást. Ha e kihívást a terminál megválaszolja a kártyával közös szimmetrikus kulcs alapján, a kártya engedélyezze a terminálnak a pénz feltöltés műveletet. Egyébként a kártya utasítsa el e műveletet. (8 pont) Értékelje e megoldás korlátait! (2 pont) Megjegyzés: A kártyától első körben kérünk egy 8 byte-os véletlent (challenge). Ezt a megfelelő 8 byte-os DES kulccsal kell rejtjelezni ECB módban a terminálon, nyilván padding nélkül. Erre szolgál a mellékelt util/desecbnopad java program. A rejtjelezett szintén 8 byte-ot visszaküldjük (response) a kártyának az APDU managerrel. Ha az így 12
visszaküldött 8 byte megegyezik a kártya által szintén hasonló módon számolt 8 bytetal, akkor a terminál sikeresen hitelesítette magát. Segítségként a kommentben szereplő SkeletonApplet.Cipher vázolja a rejtjelezés menetét a kártyán. 5. Minta beugró kérdések A beugró 5 pontot ér! 1. Mit értünk programozható kártya alatt? 2. Miért van értelme chipkártyákat magasszintű nyelven (pl. Java) programozni? 3. Melyek a legfőbb különbségek a Java Card és a Java nyelv között? 4. Mire szolgál a javacard.framework.applet osztály process metódusa? 5. Hol szokás Java Card appletekben memóriát foglalni? Miért? 6. Mi az AID? 6. Jegyzőkönyv beadása és értékelése A jegyzőkönyvet.doc,.rtf vagy.pdf formátumban kell emailen keresztül eljuttatni a következő címzéssel és tárggyal a mérés napjától számított egy héten belül (<yyyymmdd> a mérés dátumának formátuma): Subject: sc_meres_2-<yyyymmdd> To: meres@crysys.hu Beugróval együtt összesen 40 pont szerezhető. Ennek megfelelően: Hivatkozások Ponthatár Jegy 34 40 5 28 33 4 22 27 3 16 21 2 0 15 1 [1] Sun Microsystems Inc. (2000). Java Card (TM) 2.1.1 Application Programming Interface. Sun Microsystems, Inc. 901 San Antonio Road Palo Alto, CA 94303 USA 650 960-1300. http://java.sun.com/javacard [2] Chen, Z. (2000). Java Card Technology for Smart Card: Architecture and Programmer s Guide. Addison-Wesley Pub Co; ISBN: 0201703297. [3] Chen, Z. (1999). How to write a Java Card applet: A developer s guide. JavaWorld, July, 1999. http://www.javaworld.com/javaworld/jw-07-1999/jw-07-javacard_p.html [4] Berta, I. and Mann, Z. (1999). A hitelesség biztosításának lehetőségei intelligens smart card segítségével. Scientific student circle conference, Budapest University of Technology and Economics. 13
[5] Berta, I. andmann, Z. (2000). Programozható chipkártyák elmélet és gyakorlati tapasztalatok. Magyar Távközlés, 2000, vol 4. [6] Motré, S. (2000). Formal Model and Implementation of the Java Card Dynamic Security Policy. Gemplus Research Laboratory Avenue du Pic de Bertagne 13881 Gémenos CEDEX. [7] Requet, A. A B Model for Ensuring Soundness of a Large Subset of the Java Card Virtual Machine. Gemplus Research Laboratory, Av du Pic de Bertagne, 13881 Gémenos cedex BP 100. [8] Sun Microsystems (1997). Java Card 2.0 Language Subset and Virtual Machine Specification. [9] MULTOS (1999). MULTOS The multi application operating system for smart cards. http://www.multos.com [10] Schlumberger (1999). CyberflexAccess Software DevelopmentKit Programmer s Manual Release 2. [11] Ács, G., Bencsáth. B., Berta. I. (2006). Smart Card mérés I. CardOS/M4. http://www.crysys.hu 14