• No results found

Funkce realizuj´ıc´ı antikolizn´ı protokol

Navrˇzen´y n´astroj slouˇz´ı k testov´an´ı bezpeˇcnosti RFID transpond´er˚u a aplikac´ı, kter´e vyuˇz´ıvaj´ı Mifare Classic. Z tohoto d˚uvodu nebyly implementov´any konkr´etn´ı zn´am´e

´

utoky, kter´e ovˇsem lze s vytvoˇren´ymi n´astroji s urˇcit´ym ´usil´ım realizovat, ale pouze funkce pro detekci konkr´etn´ıch zranitelnost´ı.

Takto lze velice rychle vylouˇcit implementace, kter´e nelze s t´ımto vybaven´ım na-padnout, napˇr´ıklad pomoc´ı

”Dark side“ ´utoku. ´Utok na nezranitelnou implementaci

m˚uˇze b´yt spuˇstˇen hodiny a nikdy se s´am nezastav´ı, pokud tedy nen´ı implemen-tov´ano omezen´ı doby bˇehu. Ale ani takto nelze bez dalˇs´ı anal´yzy rozhodnout, proˇc

´

utok selhal.

N´astroj umoˇzˇnuje prov´adˇet n´asleduj´ıc´ı operace:

1. Testov´an´ı entropie pouˇzit´eho PRNG

2. Testov´an´ı implementac´ı odpov´ıdaj´ıc´ıch na kaˇzdou kombinaci paritn´ıch bit˚u 0x5

3. Testov´an´ı pouˇzit´ı implicitn´ıch kl´ıˇc˚u k zabr´anˇen´ı takzvan´emu Nested ´utoku 4. Vizualizace obsahu pamˇeti s moˇznost´ı manipulace pomoc´ı datov´eho modelu

4.3 N´ızko´ urovˇ nov´ e funkce a wrapper pro Python

Libnfc je knihovna urˇcen´a pro programovac´ı jazyk C, proto pro pouˇzit´ı v jazyce Python bylo nutn´e datov´e typy a vˇsechny funkce napsan´e v C obalit wrapperem.

Tento wrapper je naps´an v Pythonu pomoc´ı tˇr´ıd z knihovny ctypes.

V k´odu 4.1 je uvedena tˇr´ıda, kter´a obaluje strukturu nfc device a poskytuje metody pro obsluhu zaˇr´ızen´ı v Pythonu. Obdobn´ym zp˚usobem jsou ˇreˇseny tˇr´ıdy pro ostatn´ı nutn´e struktury a samotn´e funkce napsan´e v jazyce C.

Bohuˇzel naps´an´ı wraperu pro knihovnu Libnfc v pln´em rozsahu by bylo ˇcasovˇe n´aroˇcn´e, a proto tak´e v t´eto pr´aci byla vytvoˇrena jen mal´a ˇc´ast, kter´a byla ne-zbytn´a. Ostatn´ı ˇc´asti pak byly naps´any v jazyce C a do Pythonu byly pˇred´any pouze v´ysledky.

Celkem samotn´y wrapper obsahuje 24 tˇr´ıd.

4.3.1 NfcContext

Struktura nfc context mus´ı b´yt vytvoˇrena a inicializov´ana jako prvn´ı pˇred jakoukoliv jinou prac´ı s knihovnou Nfclib, ponˇevadˇz obsahuje intern´ı nastaven´ı a ukazatele na dalˇs´ı d˚uleˇzit´e ˇc´asti knihovny. V Pythonu byla vytvoˇrena tˇr´ıda NfcContext, kter´a obsahuje samotnou strukturu a s n´ı logicky spˇraˇzen´e funkce (inicializace a ruˇsen´ı kontextu).

4.3.2 NfcDevice

Dalˇs´ı d˚uleˇzitou ˇc´ast´ı je struktura nfc device slouˇz´ıc´ı k pˇripojen´ı k samotn´emu NFC3 zaˇr´ızen´ı. D´ale obsahuje informace nutn´e pro ˇr´ızen´ı zaˇr´ızen´ı – typ, ovladaˇc a samotn´e nastaven´ı funkce ˇcipu. V n´astroji je vytvoˇrena tˇr´ıda NfcDevice, kter´a reprezentuje tuto strukturu a jako metody m´a pˇr´ısluˇsn´e funkce (inicializace, ruˇsen´ı pˇr´ıkazu, uve-den´ı do neˇcinn´eho stavu a uzavˇren´ı zaˇr´ızen´ı).

4.3.3 N´ızko´ urovˇ nov´ e funkce

V ˇc´asti aplikace napsan´e v jazyce C byly naprogramov´any n´asleduj´ıc´ı funkce:

• transmit bytes – Umoˇzˇnuje pˇrenos dat po jednotliv´ych bajtech s t´ım, ˇze pa-ritn´ı bity jsou pˇrid´av´any a kontrolov´any hardwarovˇe. Lze vyuˇz´ıt integrovan´eho obvodu pro zv´yˇsen´ı pˇresnosti pˇresn´ym ˇr´ızen´ım ˇcasov´an´ı.

• transmit bytes par – Umoˇzˇnuje pˇrenos dat po jednotliv´ych bajtech s manu´aln´ım nastaven´ım paritn´ıch bit˚u. Tato funkce je vyuˇz´ıv´ana pˇri testov´an´ı na zranitel-nosti.

• transmit bites – Pro ´uˇcely antikolizn´ıho protokolu musela b´yt vytvoˇrena funkce pro pˇrenos dat po jednotliv´ych bitech. Ochrana pˇrenosu je rovnˇeˇz automatick´a.

• anticol – Tato funkce realizuje antikolizn´ı protokol a vyb´ır´a dostupn´y trans-pond´er.

• read – Bˇeˇzn´e ˇcten´ı dat z transpond´eru.

• write – Bˇeˇzn´y z´apis bloku do transpond´eru.

Nad tˇemito funkcemi byl v Pythonu naprogramov´an wrapper a samotn´e tˇr´ıdy pro pr´aci s NFC zaˇr´ızen´ım.

4.3.4 Ostatn´ı ˇ c´ asti

D´ale byl vytvoˇren wrapper pro:

• Struktury jednotliv´ych typ˚u transpond´er˚u (r˚uzn´e typy ISO 14443, Felica a Jewel)

3Near Field Communication

• Struktury pro datovou komunikaci (modulace, rychlost, c´ılov´e zaˇr´ızen´ı)

• Struktury specifick´e pro Mifare Classic

Zdrojov´y k´od 4.1: Wrapper pro nfc device

1 class NFC_DEVICE(Structure):

2 DEVICE_NAME_LENGTH = 256

3 DEVICE_PORT_LENGTH = 64

4

5 _fields_ = [

6 ( ’context’, POINTER( NFC_CONTEXT ) ),

7 ( ’name’, c_char * DEVICE_NAME_LENGTH ),

8 ( ’connstring’, c_char * NFC_BUFSIZE_CONNSTRING),

9 ( ’bCrc’, c_bool ),

10 ( ’bPar’, c_bool ),

11 ( ’bEasyFraming’, c_bool ),

12 ( ’bAutoIso14443_4’, c_bool ),

13 ( ’btSupportByte’, c_uint8 ),

14 ( ’last_error’, c_int )

15 ]

28 def __init__(self, context, connstring=None, libpath=LIBPATH):

29 try:

30 self.lib = CDLL(libpath)

31 except OSError as e:

32 raise e

33 else:

34 self.lib.nfc_open.restype = ctypes.POINTER( NFC_DEVICE )

35 self.device = self.lib.nfc_open( context.context, connstring )

36

37 if self.device == None:

38 raise NfcError()

47 if code != NfcError.NFC_SUCCESS:

48 raise NfcError(code)

49

50 def idle(self):

51 code = self.lib.nfc_idle(self.device)

52

53 if code != NfcError.NFC_SUCCESS:

54 raise NfcError(code)

4.4 Tˇr´ıdy pro pr´ aci s NFC zaˇr´ızen´ım

Nad wraperem, kter´y obaluje k´od knihovny Libnfc a k´od v jazyce C, jsou postaveny tˇr´ıdy pro samotnou manipulaci s transpond´erem.

4.4.1 MifareBlockStream

MifareBlockStream je z´akladn´ı tˇr´ıda realizuj´ıc´ı pˇr´ıstup k NFC zaˇr´ızen´ı. V konstruk-toru je provedeno potˇrebn´e nastaven´ı pro komunikaci s transpond´erem (modulace, pˇrenosov´a rychlost, c´ılov´a struktura) a d´ale je otevˇrena sd´ılen´a knihovna obsahuj´ıc´ı k´od pro samotnou pr´aci se zaˇr´ızen´ım.

Pro pr´aci s transpond´erem poskytuje tˇr´ıda MifareBlockStream tyto metody:

• init (libPath) – inicializace knihovny a pˇripraven´ı datov´ych struktur

• poll(device) – v´ybˇer transpond´eru

• auth(device, index, key, useKeyB) – autentizace bloku

Zavol´an´ım metody poll(nfcDevice) dojde k automatick´emu proveden´ı antiko-lizn´ıho protokolu a tedy i v´ybˇeru jednoho transpond´eru. Pˇri vol´an´ı t´eto metody je vykon´ana stejnojmenn´a funkce napsan´a v jazyce C. Pokud nastane pˇri vykon´av´an´ı antikolizn´ıho protokolu chyba, tak je vyhozena v´yjimka.

Pˇred jakoukoliv manipulac´ı s daty transpond´eru mus´ı b´yt konkr´etn´ı blok autenti-zov´an urˇcit´ym kl´ıˇcem. K tomu slouˇz´ı metoda auth(nfcDevice, index, key, useKeyB), kter´a obaluje stejnojmennou funkci napsanou v C. Metoda umoˇzˇnuje zvolit auten-tizaˇcn´ı kl´ıˇc pomoc´ı boolovsk´e promˇenn´e useKeyB. V pˇr´ıpadˇe chyby je opˇet vyhozena v´yjimka MifareException s pˇr´ısluˇsnou chybovou zpr´avou.

Od t´eto tˇr´ıdy dˇed´ı n´asleduj´ıc´ı dvˇe tˇr´ıdy pro ˇcten´ı a z´apis dat RFID transpond´eru.

Hiearchie tˇechto tˇr´ıd je zobrazena na obr´azku 4.1.

gpollTvstupKdeviceK:KNfcDeviceHK:Kbyte[4]

Obr´azek 4.1: Tˇr´ıdy pro manipulaci s pamˇet´ı transpond´eru

4.4.2 MifareBlockReader

Tˇr´ıda MifareBlockReader slouˇz´ı pro samotn´e ˇcten´ı informac´ı z pamˇeti transpond´eru, kter´a za t´ımto ´uˇcelem poskytuje metodu read(device, index).

Parametr device je reference na instanci tˇr´ıdy NfcDevice a parametr index slouˇz´ı ke specifikaci bloku, kter´y m´a b´yt pˇreˇcten. Pokud jsou data ´uspˇeˇsnˇe pˇreˇctena, tak metoda vrac´ı list ˇsestn´acti jednobajtov´ych hodnot. V pˇr´ıpadˇe chyby je vyhozena v´yjimka.

Tato metoda automaticky nespouˇst´ı autentizaˇcn´ı rutinu, takˇze je nutn´e ji pˇred samotn´ym ˇcten´ım zavolat.

4.4.3 MifareBlockWriter

K z´apisu dat do pamˇeti transpond´eru slouˇz´ı tˇr´ıda MifareBlockwriter poskytuj´ıc´ı metodu write(device, index, data). Parametr data je list jednobajtov´ych hodnot o velikosti bloku – ve standardu Mifare Classic je to 16.

Opˇet je nutn´e nejdˇr´ıve ´uspeˇsnˇe prov´est autentizaci bloku pˇred z´apisem. Nen´ı nutn´e manu´alnˇe testovat spr´avnost form´atu bloku, nebot’ tato metoda ji prov´ad´ı automaticky. N´astroj tak nepovol´ı z´apis poˇskozen´eho bloku do pamˇeti karty, takˇze se nen´ı tˇreba ob´avat permanentn´ıho zablokov´an´ı sektoru.

4.4.4 MifareException

Tˇr´ıda MifareException je ekvivalentem chybov´eho k´odu pouˇzit´eho ˇc´ast´ı aplikace napsan´e v jazyce C.

V pˇr´ıpadˇe, ˇze nˇejak´a funkce pˇri pˇrenosu dat konˇc´ı chybou, tj. vrac´ı z´apornou hod-notu, tak je vytvoˇrena nov´a instance tˇr´ıdy MifareException. Tˇr´ıda obsahuje metodu errorMessage(code), kter´a na z´akladˇe obdrˇzen´eho chybov´eho k´odu a tabulky 4.1 na-stav´ı chybovou zpr´avu. ˇR´ızen´ı je pak pˇred´ano do vyˇsˇs´ı ´urovnˇe programu k dalˇs´ımu oˇsetˇren´ı chybov´eho stavu.

4.5 Tˇr´ıdy pro testov´ an´ı zranitelnosti

4.5.1 BaseTest

BaseTest je abstraktn´ı tˇr´ıda, kter´a je pˇredkem vˇsech konkr´etn´ıch tˇr´ıd test˚u. Pˇri dˇedˇen´ı od t´eto tˇr´ıdy vˇsem potomk˚um pˇredeps´ano implementovat metodu run() slouˇz´ıc´ı k proveden´ı testu.

Tato metoda vrac´ı hodnotu, kterou lze vyhodnotit jako logick´a nepravda, pokud nebyl dan´y nedostatek detekov´an. V opaˇcn´em pˇr´ıpadˇe vrac´ı hodnotu vyhodnotitel-nou jako logick´a pravda. Tento pˇr´ıstup umoˇzˇnuje test˚um vracet r˚uzn´a data – typicky pˇr´ımo logickou hodnotu, nebo pole bajt˚u.

4.5.2 PrngDetermTest

Hodnoty z gener´atoru pseudon´ahodn´ych ˇc´ısel byly z´ısk´any pomoc´ı funkce read prngs(

nfc device *pnd, uint8 t **out, int cnt), kter´a je souˇc´ast´ı vytvoˇren´e knihovny v ja-zyce C (K´od 3.1). Tato funkce na dan´e m´ısto v pamˇeti postupnˇe uloˇz´ı z´ıskan´e ˇctyˇrbajtov´e hodnoty.

Pˇri alokaci pole pomoc´ı ctypes nast´aval probl´em se ˇspatnˇe uloˇzen´ymi daty – v urˇcit´ych pˇr´ıpadech byla v pamˇeti hodnota o nˇeco niˇzˇs´ı, neˇz b´yt mˇela. Tento probl´em byl vyˇreˇsen alokac´ı potˇrebn´eho pamˇet’ov´eho prostoru uˇz v ˇc´asti napsan´e v jazyku C.

V Pythonu bylo pak naps´ano vyhodnocen´ı n´ahodnosti pomoc´ı histogramu. Pro-gram nejdˇr´ıve z´ısk´a pomoc´ı funkce read prngs(nfc device *pnd, uint8 t **out, int cnt) pole ˇctyˇrbajtov´ych hodnot a pˇrevede je do celoˇc´ıseln´e podoby (list integer˚u).

N´aslednˇe je list seˇrazen a jsou vypoˇcteny ˇcetnosti jednotliv´ych ˇc´ısel.

4.5.3 DefaultKeysTest

Pˇri testov´an´ı bloku, zda je pˇr´ıstupn´y pomoc´ı nˇejak´eho zn´am´eho kl´ıˇce, je pouˇz´ıv´an standardn´ı slovn´ıkov´y ´utok.

Tˇr´ıda DefaultKeysTest m´a statick´y atribut keys, coˇz je list nejbˇeˇznˇejˇs´ıch impli-citn´ıch kl´ıˇc˚u, se kter´ymi v´yrobci testuj´ı funkˇcnost transpond´eru. Tyto kl´ıˇce jsou t´eˇz dostupn´e napˇr´ıklad jako souˇc´ast knihovny Libnfc.

Pˇri testov´an´ı je potˇreba vytvoˇrit instanci tˇr´ıdy MifareBlockReader a n´aslednˇe prov´est posloupnost n´asleduj´ıc´ıch operac´ı:

1. V´ybˇer dalˇs´ıho kl´ıˇce

2. Zavol´an´ı metody poll(device)

3. Zavol´an´ı metody auth(device, blockNo, key, keyB) 4. Ukonˇcen´ı nebo n´avrat k bodu 1

Po proveden´ı metody poll(device) je antikolizn´ım protokolem vybr´an transpond´er.

N´aslednˇe je zavol´ana metoda auth(device, blockNo, key, keyB), kter´a se pokus´ı s dan´ym kl´ıˇcem autentizovat (provede tedy pouˇzit´y autentizaˇcn´ı protokol). V´ystupem je logick´a hodnota, na jej´ımˇz z´akladˇe je bˇeh ukonˇcen, nebo je tato sekvence opa-kov´ana s dalˇs´ım kl´ıˇcem.

Antikolizn´ı (uveden ve zkr´acen´e verzi v k´odu 4.2) a autentitaˇcn´ı protokol je ˇreˇsen na niˇzˇs´ı ´urovni – v knihovnˇe naprogramovan´e nad Libnfc v jazyce C.

Zdrojov´y k´od 4.2: Funkce realizuj´ıc´ı antikolizn´ı protokol

1 int anticol(nfc_device *pnd) {

2 uint8_t dataRx[MAX_FRAME_LEN] = {0};

3 uint8_t dataTx[MAX_FRAME_LEN] = {0};

4 size_t sizeRx = -1;

5

6 // Request type A

7 if( (sizeRx = transmit_bits(pnd, cmd_reqa, dataRx, 7) ) < 0 ) {

8 return STATUS_ERR;

9 }

10 memcpy(abtAtqa, dataRx, 2);

11

12 // Select all

13 if( (sizeRx = transmit_bytes(pnd, cmd_select_all, dataRx, 2) ) <

0) {

14 return STATUS_ERR;

15 }

16

17 // Check answer

18 if ((dataRx[0]^dataRx[1]^dataRx[2]^dataRx[3]^dataRx[4]) != 0) {

19 return STATUS_ERR;

20 }

21 memcpy(tagUid, dataRx, sizeRx); // Save tag UID

22

23 // Create Select UID request

24 memcpy(dataTx, cmd_select_uid, sizeof(cmd_select_uid)); // Add command

25 memcpy(dataTx + 2, dataRx, MIFARECL_UID_LEN); // Add tag UID

26 iso14443a_crc_append(dataTx, 7); // Add CRC

27

28 // Transmit select(uid) request

29 if( (sizeRx = transmit_bytes(pnd, dataTx, dataRx, 9) < 0) ) {

30 return STATUS_ERR;

Tato tˇr´ıda umoˇzˇnuje testovat transpond´er na chybnˇe implementovanou kontrolu integrity. Ve skuteˇcnosti je veˇsker´y v´ykonn´y k´od prov´adˇen uvnitˇr funkce

mifare check nack prob(nfc device *pnd) uveden´e v k´odu 3.2. Tˇr´ıda NackProbTest ji jen zpˇr´ıstupˇnuje pro pouˇzit´ı v Pythonu.

Pˇri testov´an´ı se vyuˇz´ıv´a konstantn´ı hodnota v´yzvy transpond´eru nT. Nejdˇr´ıve je vybr´an transpond´er pomoc´ı funkce anticol(nfc device *pnd) a n´aslednˇe je zapoˇcata prvn´ı f´aze autentizaˇcn´ıho protokolu – z´ısk´an´ı hodnoty v´yzvy nT z transpond´eru.

Pokud tato hodnota neodpov´ıd´a hodnotˇe konstatn´ı v´yzvy, tak je karta zresetov´ana vypnut´ım nap´ajen´ı.

V pˇr´ıpadˇe, ˇze hodnota v´yzvy je konstatn´ı, tak je vygenerov´an pomoc´ı funkce next variation(uint8 t *data, size t lenght, int fixed) n´asleduj´ıc´ı kombinace hodnot bit˚u. S tˇemito paritn´ımi bity je odesl´an dalˇs´ı poˇzadavek s hodnotami {aR} {nR}.

Pokud transpond´er odpov´ı ˇctyˇrbitovou hodnotou, tak je zv´yˇsen ˇc´ıtaˇc spr´avn´ych kombinac´ı paritn´ıch bit˚u o jedna.

D´ale se postupuje stejnˇe jako v pˇredeˇsl´ych odstavc´ıch. Pokud je v´ysledn´a hodnota ˇc´ıtaˇce vyˇsˇs´ı neˇz jedna, tak se jedn´a o zranitelnˇejˇs´ı implementaci standardu.

4.6 Datov´ y model transpond´ eru

Na z´akladˇe antikolizn´ıho protokolu z´ısk´a ˇcteˇcka informaci o typu transpond´eru (SAK4). Pˇri pˇrijmut´ı hodnoty 0x08 se jedn´a o Mifare Classic s pamˇet´ı o velikosti 1 kB, a pˇri pˇrijmut´ı hodnoty 0x18 jde o 4 kB verzi transpond´eru (NXP Semiconduc-tors). Tuto skuteˇcnost bylo nutn´e zohlednit i pˇri n´avrhu programu.

YgetValueD_,:,byte[26]

Obr´azek 4.2: Datov´y model

4Select Acknowledge, Type A

4.6.1 MifareModel

Ve chv´ıli, kdy se program pokus´ı poprv´e naˇc´ıst data z pamˇeti transpond´eru, tak mus´ı b´yt proveden jeho v´ybˇer antikolizn´ım protokolem. Podle v´ysledku je vytvoˇrena instance tˇr´ıdy Mifare1kModel, nebo instance tˇr´ıdy Mifare4kModel (Obr´azek 4.2).

D´ale je pr´ace s tˇemito moˇzn´ymi transpond´ery identick´a, liˇs´ı se jen nutnost´ı vy-hradit r˚uznˇe velk´e m´ısto v pamˇeti.

4.6.2 SectorModel

Kaˇzd´y Mifare Classic transpond´er se skl´ad´a z urˇcit´eho mnoˇzstv´ı sektor˚u (z´aleˇz´ı na typu), kter´e jsou v programu reprezentov´any tˇr´ıdou SectorModel. Ponˇevadˇz pro oba dva typy transpond´er˚u je sektor stejn´eho form´atu, tak je moˇzn´e m´ıt pouze jednu tˇr´ıdu, kter´a pop´ıˇse oba typy. V t´eto tˇr´ıdˇe je ˇreˇsen pˇr´ıstup a manipulace s jednotliv´ymi bloky s t´ım, ˇze je pouˇzito pˇr´ım´e indexov´an´ı blok˚u a pˇrepoˇcet indexu na sektor/blok prob´ıh´a internˇe.

SectorModel m´a implementov´any metody pro pˇr´ıstup/manipulaci s bloky (get-Block, setBlock) a zodpov´ıd´a za vytvoˇren´ı samotn´ych blok˚u – instanc´ı tˇr´ıdy BlockMo-del. Pˇri z´apisu bloku tato tˇr´ıda automaticky kontroluje form´at, aby nemohlo doj´ıt k nechtˇen´emu permanentn´ımu zablokov´an´ı sektoru z d˚uvodu z´apisu poˇskozen´eho konfiguraˇcn´ıho bloku (metoda checkTrailer zobrazen´a v k´odu 4.3).