Úvod
Nejtypičtějšími zástupci smartkaret, které pravděpodobně budete znát, jsou SIM karty, bankomatové EMV karty nebo různé bezkontaktní ISO14443 karty, jako třeba varianty Mifare, a biometrické pasy. Pro kryptografické smartkarty s USB rozhraním se často používá výraz „kryptotoken“.
Základní úlohou kryptotokenů je udržet nějaké „nekopírovatelné tajemství“, typicky symetrický nebo asymetrický klíč a povolit s ním jen několik operací – dešifrování, podpis nebo autentizaci. Jednodušší smartkarty slouží jako „kontejner“ pro pár bajtů dat (Mifare Ultralight).
Smartkarty jsou integrované čipové karty „točící se kolem“ ISO-7816, což ve zkratce znamená, že ze softwarového hlediska komunikují přes APDU (application protocol data unit). APDU jsou něco jako „assembler“ pro smartkarty. Hypoteticky jsou standardizovány v ISO-7816, prakticky se velmi liší jak v různých třídách (SIM, EMV…), tak mezi výrobci. Proprietární a nedokumentované instrukce jsou všudypřítomné (proto ten výraz „točící se kolem“).
Bugy jak v smartkartách i jejich ovladačích jsou velmi rozšířené a často bizarní. Mám pocit, že smartkarty víc než standard představují ohromný soubor speciálních případů. Prý se dokonce někdy chyby standardizují, protože spolu s přeprogramováním čteček/bankomatů je to levnější, než vyměnit miliony existujících karet.
V rámci testování smartkaret jsme v Laboratořích CZ.NIC opravili několik bugů v OpenSC pro Feitian ePass 2003 PKCS#11 modulu, například nemožnost importovat RSA klíče s veřejným exponentem jiným než 65537 – starší SSH RSA klíče obsahují veřejný exponent 35.
Podle chyb vyjmenovaných v tomto článku by se někomu mohlo zdát, že absolutně nic nefunguje; ale není tomu tak. Většina problémů je spojena spíše s uživatelskou přívětivostí než s bezpečností.
Popsané chyby jsou spíš důsledkem obrovského množství zapojených vrstev protokolů a standardů:
- PKCS#11 – C-čkové API pro HSM (hardware security module)
- PKCS#15 – formát souborů/objektů na kryptografické smartkartě
- X.509, PKCS#1 – formát certifikátů a klíčů
- USB-CCID – nízkoúrovňové API pro komunikaci smartkaret přes USB
- ISO-7816 – specifikace smartkaret, formáty zpráv pro komunikaci (APDU)
- OpenPGP card – formát smartkaret pro použití s PGP/GnuPG, který je velmi rozdílný od PKCS#15, ale existuje způsob (dost složitý), jak ho s PKCS#15 emulovat
- RFC 4880 – formát zpráv OpenPGP (OpenPGP packet format)
- ISO 14443, ISO 15693 a mnoho vrstev pro zpětnou kompatibilitu u RFID karet
- a např. Mifare DESfire používají nativní nebo „obalovaný“ formát zpráv (můžete si to představit jako tunelování protokolů)
Pro názornost: diagram NFC stacku pochází z analýzy slabin implementace NFC protokolu:
Čtečky a nástroje
Pro čtení smartkaret je očekávatelně nutná čtečka. USB tokeny jsou v zásadě smartkarta, natvrdo nadrátovaná ke čtečce. Pro multiplatformní podporu je dobré vybírat takový hardware, který je podporován v pcsc-lite. Populární je například čtečka HID Omnikey Cardman 5321, která funguje s pcsc-lite rovnou – tedy alespoň její kontaktní část.
Pro RFID část Cardmana je nutno nainstalovat do systému binární blob, ke kterému pokud vím nejsou zdrojáky a existuje jen pro x86 a x86_64 platformy a člověk velmi rychle odhalí několik bugů. V binárním blobu někdo zapomněl RPATH (RPATH určuje extra adresáře, kde se budou hledat sdílené knihovny a PC/SC daemon běží pod rootem):
$ readelf -d ifdokrfid.so | grep RPATH 0x000000000000000f (RPATH) Library rpath: [/home/mhofer/ps/prfx/lib]
Další bizarní bug způsobuje, že dokud je tenhle RFID blob nahraný, tak nelze číst kontaktní karty vydané jednou specifickou bankou – čtečka se zacyklila. Poslední překvapivá vlastnost je nemožnost čtení emulovaných Mifare 1k karet – v dokumentaci existuje nastavení hodnoty registrů ve Windows, pro jiné OS jsme řešení nenašli.
K této čtečce existuje navíc také low-level knihovna librfid, která by měla umožňovat nízkoúrovňové čtení RFID protokolu, ale bohužel knihovna je už dlouho neudržována a zdá se, že se za tu dobu ve čtečce změnil firmware. USB interface descriptor neodpovídá tomu, co knihovna hledá a nepovedlo se librfid zprovoznit ani po mírném přiohnutí kódu. Další knihovna libnfc podporuje jenom novější čip PN532 (přítomen třeba v jiné populární RFID čtečče ACR122U).
Několik dalších nástrojů, nezávislých na HW čtečky:
- OpenSC – opensc-tool se hodí na posílání syrových APDU, navíc občas projevuje „fuzzovací inteligenci“, např. zkusí při chybě víc forem APDU
- RFIDIot – hodí se především k dekódování různých RFID karet, lze číst i biometrické pasy. Občas ale rfidiot-cli utilita nesprávně posílá navíc v APDU nulové bajty
- cardpeek – GUI a framework pro dekódování smartkaret, dekódovací skripty se píšou v Lua. Mají pěkně udělaný dekodér pro EMV karty, funguje na kontaktní i NFC platební karty.
- javaemvreader – další EMV dekodér, umí dekódovat i jiné věci než cardpeek
Na EMV kartách je uložena velká spousta informací, od jazykových preferencí a údajích o jejím držiteli, přes PKI certifikáty až po veřejné RSA klíče vydavatele (certifikáty nejsou v X.509 formátu). Obrázek nahoře ukazuje historii transakcí provedených kartou. Typicky jsme viděli historii do 20 položek, ale prý existují karty ukládající si i 100 posledních transakcí. Čtení EMV karet přes NFC interface dávalo konzistentnější výsledky než čtení čipu, u čipu to bylo snad co karta, to unikát. EMV standard je sám o sobě dosti obsáhlý, několik zajímavých prací lze najít u Stevena J. Murdocha.
Další možností jak přečíst RFID karty je nějaké zařízení s Androidem a NFC čtečkou, která už mají dost dobře odladěnou podporu pro čtení ISO 14443/15693 RFID karet. Jako zástupce čtecí aplikace pro Android bychom mohli vybrat například NFC TagInfo umí zobrazit množství informací o kartě.
Komunikace se smartkartou – ATR a APDU
ATR, zkratka z answer to reset je první zpráva od smartkarty po jejím resetu nebo připojení. Obsahuje informace, jakým způsoben s ní komunikovat a lze podle ní určit karty nebo výrobce. U RFID karet někdy ATR emuluje čtečka.
APDU, application protocol data unit je zmiňovaný „assembler smartkaret“. APDU odcházející ke smartkartě má formát:
CLA INS P1 P2 Lc Data Le
Všechny uvedené části, až na Data, mají jeden byte, část Data ma variabilní délku. Položky Lc, Data, Le můžou chybět, závisí na typu karty, výrobci a instrukci. V praxi je tudíž možných tvarů APDU přes deset – existují i rozšířené APDU, aby šlo posílat víc než jen 255 bajtů dat – ty pak můžou mít Lc a Le dlouhé 3 bajty.
CLA značí class, třídu instrukce. Hodnota 0×0N je pro standardní ISO 7816, 0×8N-0×9N pro proprietární instrukce karty nebo GlobalPlatform instrukce. Hodnota 0×FF je k vidění u Mifare 1k, 0×90 u Mifare DESfire pro nativní příkazy obalené do ISO 7816 APDU.
INS označuje opkód instrukce, která se má vykonat, parametry P1 a P2 závisí na instrukci. Lc je počet datových bajtů posílaných v Data, Le je počet očekávaných bajtů. Rychlý přehled základních instrukcí lze nalézt v krátké referenci ISO-7816–4 příkazů.
Karta vrátí odpověď jako příchozí APDU s jednodušším formátem: několik dat bajtů následovaných dvěma bajty návratového kódu. Návratový kód 0×9000 značí, že operace skončila bezchybně, 0×6A82 značí že soubor nebo aplikace neexistuje. Můžete se podívat na tabulku některých běžných návratových kódů. Opět existují kromě standardních navíc i specifické návratové kódy pro různé třídy a výrobce.
Příklad: výběr souboru 0×5015 pro PKCS#15 aplikaci vypadá s instrukcí 0×A4 (SELECT) použitím opensc-tool následovně (přepínač -s slouží k zaslání APDU):
% opensc-tool -s "00 A4 00 00 02 50 15" Using reader with a card: Feitian ePass2003 00 00 Sending: 00 A4 00 00 02 50 15 Received (SW1=0x90, SW2=0x00): 6F 24 82 02 38 00 83 02 50 15 84 0C A0 00 00 00 o$..8...P....... 63 50 4B 43 53 2D 31 35 85 02 00 7F 86 08 90 90 cPKCS-15........ FF 90 FF FF FF FF ......
V předchozí APDU máme podle předchozího schématu CLA=0×00, INS=0×A4, P1=0×00, P2=0×00, Lc=0×02 a dva datové bajty 0×50 0×15. Le je vynecháno.
Část „SW1=0×90, SW2=0×00“ jsou dva bajty návratového kódu, operace skončila bez chyby. Několik dalších příkladů standardních instrukcí:
- ERASE FILE – instrukce 0×E4
- 00 E4 00 00 02 3F 00 – smaže soubor 0×3F00
- GENERATE KEY PAIR – instrukce 0×46
- 00 46 00 00 07 01 08 00 29 00 30 00 – vygeneruje pár RSA klíčů, privátní uloží do souboru 0×2900, veřejný do 0×3000
Ukažme si také komunikaci s bezkontaktní NFC kartou. Přečtení NFC NDEF type 4 zprávy využívá instrukce A4 jak na výběr aplikace, tak na výběr souboru. Použijou se tyto tři APDU:
- nejprve se vybere NDEF Tag aplikace s AID D2760000850101
- 00 A4 04 00 07 D2 76 00 00 85 01 01 00
- pak se vybere soubor 0×E104 obsahující NDEF zprávu
- 00 A4 00 0C 02 E1 04
- instrukce 0×B0 značí už samotné přečtení záznamu (READ BINARY)
- 00 B0 00 00 00
Správně podle specifikace bychom si měli zjistit z Capability Container-u, v jakém souboru se NDEF zpráva nachází. Pro jednoduchost je to v předchozím příkladě vynecháno, běžná hodnota bývá právě 0×E104.
Reverzování proprietárních instrukcí
Někdy mohou chybové kódy pomoci ke zjištění existence proprietárních APDU a jejich správného volání. Kód 6E00 říká, že třída CLA není podporována, kód 6D00, že instrukce není podporována. Chybový kód 6700 značí, že CLA i INS jsou správně, ale neposíláme správný počet dat a nebo je chybně Lc/Le.
Podobně se nám povedlo najít nedokumentovanou instrukci pro výpis souborů u Feitian ePass 2003 a nestandardnost u EMV karet – Oberthur karty při SELECT AID vyžadovaly vynechání Le bajtu, jinak selhala až další instrukce.
Kryptotokeny
Podrobněji jsme vyzkoušeli tyto tři kryptografické tokeny:
Na obrázku jsou odshora Yubikey Standard, Yubikey Neo, Feitian ePass 2003 a ještě jednou ePass 2003, tentokrát otevřený. Poslední ePass 2003 jsme otevřeli proto, že se ho povedlo během experimentování „bricknout“.
Největší čip uprostřed ePass-u je místem, kde se odehrává všechna ta kryptografie, kolem jsou jen nepodstatné drobnosti (regulátor napětí, dioda, kondenzátory, rezistory). Mělo by se jednat o ST23YT66, i když na krytu čipu je napsáno něco úplně jiného.
Podrobné výsledky těchto testů naleznete v pokračování tohoto seriálu za týden.