diff --git a/README.md b/README.md index 414ff1c..344a523 100644 --- a/README.md +++ b/README.md @@ -77,21 +77,23 @@ The demo application (`demoapp/app`) provides a complete reference implementatio * `libs/id-card-lib/build/outputs/aar` * `libs/smart-card-reader-lib/build/outputs/aar` * Move the resulting `.aar` files to your project's `/libs` directory. -* Add the corresponding dependencies to your application's `build.gradle` file: - * `implementation files('app/libs/aar')` +* Add the dependencies to your application's `build.gradle` file: + * `implementation files('app/libs/id-card-lib.aar')` + * `implementation files('app/libs/smart-card-reader-lib.aar')` ## Overview ID card support for Android applications is based on two libraries: `id-card-lib` and `smart-card-reader-lib`. -* `smart-card-reader-lib` enables the use of the ID card over USB or NFC. It provides the low-level smart card reader interfaces and communication layer. +* `smart-card-reader-lib` enables the use of the ID card over NFC. It provides the NFC smart card reader interface and communication layer. * `id-card-lib` implements the APDU-based communication protocols required to use the core functionality across different types of ID cards (IDEMIA and Thales). + Integrating ID card support into an Android application proceeds as follows: -* The developer declares the permissions required for the chosen integration method in the application manifest. -* The developer creates a manager specific to the selected integration method. -* Using the manager, the developer detects the ID card and creates a card instance via the appropriate `factory` method. -* The developer establishes a secure communication channel between the card and the device using the card’s corresponding CAN code. +* The developer declares the NFC permission in the application manifest. +* The developer creates an `NfcSmartCardReaderManager` instance. +* Using the manager, the developer detects the ID card and creates a card instance via `TokenWithPace.create()`. +* The developer establishes a secure communication channel between the card and the device using the card’s CAN code. * The developer communicates with the card instance to use the desired functionalities—authentication, digital signing, etc. An example of using the NFC interface can be found in the demo application: `CardReaderFragment.kt`. The example is written in Kotlin, but the library can also be used in Java applications. The sample app additionally depends on the `libdigidocpp` library, which enables the creation of signed ASiC-E containers; however, this dependency is not required for using the ID card via NFC. @@ -149,7 +151,7 @@ public interface TokenWithPace extends Token { The `TokenWithPace` interface enables NFC communication with the ID card. An instance is obtained via its `create` factory method, which selects the correct implementation based on the card's ATS (*Answer To Select*). -Currently, two NFC-enabled ID card types are supported: IDEMIA (ID1) and Thales, implemented as `ID1WithPace` and `ThalesWithPace`. +Currently, two NFC-enabled ID card types are supported: IDEMIA and Thales, implemented as `IdemiaWithPace` and `ThalesWithPace`. After creating the instance, establish the communication channel using the card’s `CAN` code and the `tunnel` method. @@ -263,27 +265,19 @@ private fun exceptionHandler(ex: SmartCardReaderException) { ### Specifics of the NFC Interface -In general, using the ID card over **USB** and **NFC** interfaces is quite similar — -the main functions are the same, and the APDU protocol is largely identical. -However, the NFC interface has certain characteristics that may require adjustments in the application UI or communication flow. - -1. When the ID card is connected to a smart card reader via the device’s USB port, - it becomes immediately visible to the system, and certain functionalities — such as reading personal data or checking PIN retry counters — are available right away. - The card can remain inserted for long periods and does not require the user to hold it in place. - The user has time to interact with the device and enter any necessary information. +The NFC interface has certain characteristics that require attention in the application UI and communication flow. - When using the ID card via NFC, the user must know the NFC antenna’s location on the device and physically hold the card against it. +1. The user must know the NFC antenna’s location on the device and physically hold the card against it. This is often inconvenient and unstable. Additionally, the card cannot be accessed before a secure channel is established using the correct CAN code — for example, it is not possible to read PIN retry counters or display warnings to the user beforehand. While the user is holding the card near the NFC interface, it can be difficult to operate the device otherwise (e.g., to enter PIN or CAN codes). -2. When using the ID card via a USB smart card reader, the APDU protocol operates in plaintext. - Over the NFC interface, the APDU protocol is **encrypted and authenticated**. - Furthermore, the card may enforce additional restrictions — not all functionalities are available over NFC. +2. Over NFC, the APDU protocol is **encrypted and authenticated** using Secure Messaging. + The card may also enforce additional restrictions — not all functionalities are available over NFC. -3. The **CAN** is a six-digit, card-specific number required for communication with the card over NFC. +3. The **CAN** is a six-digit, card-specific number required to establish the PACE tunnel over NFC. Unlike PIN codes, the CAN cannot be changed or locked. As a protection mechanism against brute-force attempts, IDEMIA cards introduce a delay: after 10 consecutive incorrect CAN entries, the card enforces a **30-second delay** before the next CAN validation. - Once the correct CAN is entered, normal operation resumes immediately. + Once the correct CAN is entered, normal operation resumes immediately. diff --git a/doc/arhitektuur.md b/doc/arhitektuur.md index 0ff67d3..78021ec 100644 --- a/doc/arhitektuur.md +++ b/doc/arhitektuur.md @@ -135,7 +135,7 @@ Tuleb pidada silmas, et 100% ühilduvuse saavutamine ei osutunud võimalikuks. L `smart-card-reader-lib` on RIA MOPP-Android päritolu. Algselt oli tegu teegiga, mis pakkus abstraktset `SmartCardReader` liidest ning `SmartCardReaderManager` klassi, mis Android API vahendusel USB ühendusi monitooris ning ID-kaardi ühendumise tuvastas. Teek sisaldas tuge ACS ja Identiv kaardilugejatele. -NFC liidese loomise käigus refaktoreeriti USB liidese spetsiifiline kood eraldi alamteeki ning selle kõrvale loodi NFC spetsiifiline alamteek, mis realiseerib klassid `NfcSmartCardReaderManager` ja `NfcSmartCardReader`. Mõlemad alamteegid - USB ja NFC - jagavad `SmartCardReader` abstraktsiooni ja erindeid. Tulenevalt tehnoloogilistest eripäradest ei osutunud otstarbekaks haldurklasside - `UsbSmartCardReaderManager` ja `NfcSmartCardReaderManager` vaheline abstraktsioonide jagamine. Ilmselt on ka teegi kasutajal oluline teha vahet USB ja NFC liidese vahel, kuna need tingivad ka erinevad kasutajakogemused - USB kaardilugejas võib kaart olla pikalt ning rakendus saab sellega suhelda. NFC ühenduse hoidmine eeldab kasutajalt füüsilist pingutust ning kaardiga suhelda saab alles peale PACE tunneli loomist. +USB liidese spetsiifiline kood ning ACS ja Identiv kaardilugejate tugi on teegist eemaldatud. Teek realiseerib ainult NFC-spetsiifilised klassid `NfcSmartCardReaderManager` ja `NfcSmartCardReader`, mis jagavad `SmartCardReader` abstraktsiooni ja erindeid. NFC ühenduse hoidmine eeldab kasutajalt füüsilist pingutust ning kaardiga suhelda saab alles peale PACE tunneli loomist. Klass `NfcSmartCardReaderManager` on liidestumise alguspunkt integreerijale - selle klassi instantsi abil tuvastatakse seadme NFC toe olemasolu ning olek ja reageeritakse NFC võimelise ID-kaardi ilmumisele seadme kuuldeulatusse. Viimaseks otstarbeks on realiseeritud Android NFC liidese spetsiifilised *callbackid* ning integraator peab enda koodis keskenduma ennekõike ID-kaardi funktsionaalsuse kasutamisele, mitte Androidi ja ID-kaardi septsiifikale. @@ -147,19 +147,19 @@ Klass `NfcSmartCardReader` realiseerib `SmartCardReader` liidese. Siin luuakse I `id-card-lib` on RIA MOPP-Android päritolu. Kui rakendus on `smart-card-reader-lib` abil saanud `SmartCardReader` instantsi, siis antud teegi *factory* meetodeid kasutades luuakse juba konkreetset tüüpi ID-kaardi suhtlusprotokolli realiseerivad klassid, mis muuhulgas implementeerivad `Token` liidest. -USB ühenduse korral kasutab liidese `Token` *factory* meetod kaardi ATR väärtust konkreetse instantseeritava alamklassi tuvastamiseks. NFC ühenduse korral tuleb tuvastada kaardi ATS väärtus ning edasise suhtlemise jätkamiseks luua PACE protokolli kasutades autenditud ja krüpteeritud suhtluskanal kaardi ja seadme vahele. Selleks on `Token` liidesest päritud `TokenWithPace` liides, mille *factory* meetod tuvastab vaid NFC võimelisi kaarte ning mis kirjeldab meetodi `tunnel`, mida liidest implementeeriv klass peab realiseerima. +NFC ühenduse korral tuleb tuvastada kaardi ATS väärtus ning edasise suhtlemise jätkamiseks luua PACE protokolli kasutades autenditud ja krüpteeritud suhtluskanal kaardi ja seadme vahele. Selleks on `Token` liidesest päritud `TokenWithPace` liides, mille *factory* meetod tuvastab NFC võimelisi kaarte ATS väärtuse põhjal ning kirjeldab meetodi `tunnel`, mida liidest implementeeriv klass peab realiseerima. -`Token` liidest realiseerivad klassid `EstEIDv3d4` ja `EstEIDv3d5` ning `ID1`. Neist viimane kirjeldab IDEMIA ID1 kaardi APDU protokolli. +`Token` liidest realiseerivad klassid `Thales` ja `Idemia`. Neist viimane kirjeldab IDEMIA kaardi APDU protokolli. -`TokenWithPace` liidest realiseerib klass `ID1WithPace`, mis on klassi `ID1` alamklass ning täiendavalt realiseerib `ApduEncryptor` liidese, olles valmis `smart-card-reader-lib'i` klassile `NfcSmartCardReader` *Secure Messaging* sõnumite krüpteerimis-/dekrüpteerimisteenust pakkuma. +`TokenWithPace` liidest realiseerivad klassid `ThalesWithPace` ja `IdemiaWithPace`, mis on vastavate baasklasside alamklassid ning täiendavalt realiseerivad `ApduEncryptor` liidese, olles valmis `smart-card-reader-lib'i` klassile `NfcSmartCardReader` *Secure Messaging* sõnumite krüpteerimis-/dekrüpteerimisteenust pakkuma. -Klass `ID1WithPace` realiseerib ID-kaardi aspektid, mis on vajalikud NFC ühenduse vahendusel kasutamiseks: +Klassid `ThalesWithPace` ja `IdemiaWithPace` realiseerivad ID-kaardi aspektid, mis on vajalikud NFC ühenduse vahendusel kasutamiseks: * PACE protokolli abil kaardi ja seadme vahele turvalise suhtluskanali loomine * C-APDU sõnumite krüpteerimine ja MACimine - DO85, DO87, DO97 ning DO8E andmeobjektide loomine * R-APDU sõnumite dekrüpteerimine ja verifitseerimine - DO85, DO87, DO99 ning DO8E andmeobjektide töötlemine -Väärib märkimist, et vaid üks `ID1` klassi meetod on vajanud ülelaadimist APDU protokolli täpsustamiseks, kuna kaardi käitumine NFC ühenduse korral erineb käitumisest kaardilugejaga ühenduse korral, siiski tuleb öelda, et kuigi kõik klassi `ID1` poolt pakutavad funktsioonid on `ID1WithPace` poolt SM sõnumiteks teisendatavad, ei pruugi kogu kaardi funktsionaalsus olla üle NFC toetatud - nt. PUK koodide muutmine vms. +Kuigi kõik baasklasside poolt pakutavad funktsioonid on `WithPace` klasside poolt SM sõnumiteks teisendatavad, ei pruugi kogu kaardi funktsionaalsus olla üle NFC toetatud - nt. PUK koodide muutmine vms. diff --git a/doc/model/id-card.puml b/doc/model/id-card.puml index 727f26f..caa6e97 100644 --- a/doc/model/id-card.puml +++ b/doc/model/id-card.puml @@ -2,18 +2,17 @@ left to right direction -abstract class ee.ria.DigiDoc.idcard.EstEIDToken abstract class ee.ria.DigiDoc.idcard.PersonalData abstract class ee.ria.DigiDoc.smartcardreader.SmartCardReader -class ee.ria.DigiDoc.idcard.AlgorithmUtils class ee.ria.DigiDoc.idcard.CodeVerificationException -class ee.ria.DigiDoc.idcard.EstEIDv3d4 -class ee.ria.DigiDoc.idcard.EstEIDv3d5 -class ee.ria.DigiDoc.idcard.ID1 -class ee.ria.DigiDoc.idcard.ID1PersonalDataParser -class ee.ria.DigiDoc.idcard.ID1WithPace class ee.ria.DigiDoc.idcard.IdCardException +class ee.ria.DigiDoc.idcard.Idemia +class ee.ria.DigiDoc.idcard.IdemiaPersonalDataParser +class ee.ria.DigiDoc.idcard.IdemiaWithPace class ee.ria.DigiDoc.idcard.PaceTunnelException +class ee.ria.DigiDoc.idcard.Thales +class ee.ria.DigiDoc.idcard.ThalesPersonalDataParser +class ee.ria.DigiDoc.idcard.ThalesWithPace class ee.ria.DigiDoc.smartcardreader.ApduResponseException class ee.ria.DigiDoc.smartcardreader.SmartCardReaderException class ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader @@ -39,28 +38,30 @@ package org.bouncycastle <> { package util {} } +enum ee.ria.DigiDoc.idcard.CardType enum ee.ria.DigiDoc.idcard.CertificateType enum ee.ria.DigiDoc.idcard.CodeType interface ee.ria.DigiDoc.idcard.Token interface ee.ria.DigiDoc.idcard.TokenWithPace -interface ee.ria.DigiDoc.smartcardreader.SmartCardReaderManager interface ee.ria.DigiDoc.smartcardreader.nfc.ApduEncryptor -ee.ria.DigiDoc.idcard.EstEIDToken ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.idcard.EstEIDToken ..> ee.ria.DigiDoc.idcard.AlgorithmUtils -ee.ria.DigiDoc.idcard.EstEIDToken -up-|> ee.ria.DigiDoc.idcard.Token -ee.ria.DigiDoc.idcard.EstEIDv3d4 -up-|> ee.ria.DigiDoc.idcard.EstEIDToken -ee.ria.DigiDoc.idcard.EstEIDv3d4 ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.idcard.EstEIDv3d5 -up-|> ee.ria.DigiDoc.idcard.EstEIDToken -ee.ria.DigiDoc.idcard.EstEIDv3d5 ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.idcard.ID1 ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.idcard.ID1 -up-|> ee.ria.DigiDoc.idcard.Token -ee.ria.DigiDoc.idcard.ID1WithPace -up-|> ee.ria.DigiDoc.idcard.ID1 -ee.ria.DigiDoc.idcard.ID1WithPace ..> ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader -ee.ria.DigiDoc.idcard.ID1WithPace -up-|> ee.ria.DigiDoc.idcard.TokenWithPace -ee.ria.DigiDoc.idcard.ID1WithPace -up-|> ee.ria.DigiDoc.smartcardreader.nfc.ApduEncryptor +ee.ria.DigiDoc.idcard.Thales -up-|> ee.ria.DigiDoc.idcard.Token +ee.ria.DigiDoc.idcard.Thales ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader +ee.ria.DigiDoc.idcard.Thales ..> ee.ria.DigiDoc.idcard.ThalesPersonalDataParser +ee.ria.DigiDoc.idcard.ThalesWithPace -up-|> ee.ria.DigiDoc.idcard.Thales +ee.ria.DigiDoc.idcard.ThalesWithPace -up-|> ee.ria.DigiDoc.idcard.TokenWithPace +ee.ria.DigiDoc.idcard.ThalesWithPace -up-|> ee.ria.DigiDoc.smartcardreader.nfc.ApduEncryptor +ee.ria.DigiDoc.idcard.ThalesWithPace ..> ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader +ee.ria.DigiDoc.idcard.Idemia -up-|> ee.ria.DigiDoc.idcard.Token +ee.ria.DigiDoc.idcard.Idemia ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader +ee.ria.DigiDoc.idcard.Idemia ..> ee.ria.DigiDoc.idcard.IdemiaPersonalDataParser +ee.ria.DigiDoc.idcard.IdemiaWithPace -up-|> ee.ria.DigiDoc.idcard.Idemia +ee.ria.DigiDoc.idcard.IdemiaWithPace -up-|> ee.ria.DigiDoc.idcard.TokenWithPace +ee.ria.DigiDoc.idcard.IdemiaWithPace -up-|> ee.ria.DigiDoc.smartcardreader.nfc.ApduEncryptor +ee.ria.DigiDoc.idcard.IdemiaWithPace ..> ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader ee.ria.DigiDoc.idcard.Token ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader ee.ria.DigiDoc.idcard.TokenWithPace ..> ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader ee.ria.DigiDoc.idcard.TokenWithPace -up-|> ee.ria.DigiDoc.idcard.Token +ee.ria.DigiDoc.idcard.PersonalData ..> ee.ria.DigiDoc.idcard.CardType @enduml diff --git a/doc/model/smart-card-reader.png b/doc/model/smart-card-reader.png deleted file mode 100644 index f8356bc..0000000 Binary files a/doc/model/smart-card-reader.png and /dev/null differ diff --git a/doc/model/smart-card-reader.puml b/doc/model/smart-card-reader.puml index 0e54eea..58d821c 100644 --- a/doc/model/smart-card-reader.puml +++ b/doc/model/smart-card-reader.puml @@ -5,27 +5,11 @@ left to right direction package ee.ria.DigiDoc.idcard {} abstract class ee.ria.DigiDoc.smartcardreader.SmartCardReader -abstract class ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReader -package "com" as ee.ria.DigiDoc.smartcardreader.usb.com <> { - package acs {} - package identive {} -} class ee.ria.DigiDoc.smartcardreader.ApduResponseException -class ee.ria.DigiDoc.smartcardreader.BuildConfig class ee.ria.DigiDoc.smartcardreader.SmartCardReaderException class ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader class ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReaderManager -class ee.ria.DigiDoc.smartcardreader.usb.AcsUsbSmartCardReader -class ee.ria.DigiDoc.smartcardreader.usb.IdentivUsbSmartCardReader -class ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager -class ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe - -package "core" as ee.ria.DigiDoc.smartcardreader.io.reactivex.rxjava3.core <> { - class Observable - class ObservableEmitter - interface ObservableOnSubscribe -} package java <> { package io {} @@ -43,30 +27,11 @@ package "nfc" as ee.ria.DigiDoc.smartcardreader.nfc.android.nfc <> { interface NfcAdapter.ReaderCallback } -package "usb" as ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb <> { - class UsbDevice - class UsbManager -} - -package "content" as ee.ria.DigiDoc.smartcardreader.usb.android.content <> { - class BroadcastReceiver - class Context - class Intent - class IntentFilter -} - - package "android" as ee.ria.DigiDoc.smartcardreader.android <> { class app.Activity - class app.PendingIntent } - -enum ee.ria.DigiDoc.smartcardreader.SmartCardReaderStatus -interface ee.ria.DigiDoc.smartcardreader.SmartCardReaderManager interface ee.ria.DigiDoc.smartcardreader.nfc.ApduEncryptor -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReader -up-|> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbDevice ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader -up-|> ee.ria.DigiDoc.smartcardreader.SmartCardReader ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.nfc.android.nfc.Tag ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.nfc.android.nfc.tech.IsoDep @@ -74,32 +39,4 @@ ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReaderManager ..> ee.ria.DigiDoc. ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.nfc.android.nfc.NfcAdapter ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.nfc.android.nfc.Tag ee.ria.DigiDoc.smartcardreader.nfc.NfcSmartCardReaderManager -up-|> ee.ria.DigiDoc.smartcardreader.nfc.android.nfc.NfcAdapter.ReaderCallback -ee.ria.DigiDoc.smartcardreader.usb.AcsUsbSmartCardReader -up-|> ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReader -ee.ria.DigiDoc.smartcardreader.usb.AcsUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbDevice -ee.ria.DigiDoc.smartcardreader.usb.AcsUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbManager -ee.ria.DigiDoc.smartcardreader.usb.AcsUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.com.acs -ee.ria.DigiDoc.smartcardreader.usb.IdentivUsbSmartCardReader -up-|> ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReader -ee.ria.DigiDoc.smartcardreader.usb.IdentivUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.android.content.Context -ee.ria.DigiDoc.smartcardreader.usb.IdentivUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbDevice -ee.ria.DigiDoc.smartcardreader.usb.IdentivUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbManager -ee.ria.DigiDoc.smartcardreader.usb.IdentivUsbSmartCardReader ..> ee.ria.DigiDoc.smartcardreader.usb.com.identive -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.usb.android.content.Context -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbDevice -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbManager -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.io.reactivex.rxjava3.core.Observable -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.SmartCardReaderStatus -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderManager -up-|> ee.ria.DigiDoc.smartcardreader.SmartCardReaderManager -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.SmartCardReader -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.android.app.PendingIntent -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.usb.android.content.BroadcastReceiver -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.usb.android.content.Context -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.usb.android.content.Intent -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.usb.android.content.IntentFilter -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbDevice -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.usb.android.hardware.usb.UsbManager -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.BuildConfig -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe ..> ee.ria.DigiDoc.smartcardreader.io.reactivex.rxjava3.core.ObservableEmitter -ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReaderOnSubscribe -up-|> ee.ria.DigiDoc.smartcardreader.io.reactivex.rxjava3.core.ObservableOnSubscribe -ee.ria.DigiDoc.smartcardreader.SmartCardReaderManager ..> ee.ria.DigiDoc.smartcardreader.io.reactivex.rxjava3.core.Observable @enduml diff --git a/doc/model/smart-card-reader.svg b/doc/model/smart-card-reader.svg deleted file mode 100644 index ae52ee5..0000000 --- a/doc/model/smart-card-reader.svg +++ /dev/null @@ -1 +0,0 @@ -eeriaDigiDocsmartcardreaderusbcom«External»androidhardwareusb«External»content«External»nfcandroidnfc«External»techNfcAdapterioreactivexrxjava3core«External»android«External»appjava«External»orgbouncycastle«External»ee.ria.DigiDoc.idcardSmartCardReaderApduResponseExceptionBuildConfigSmartCardReaderExceptionSmartCardReaderStatusSmartCardReaderManagerUsbSmartCardReaderAcsUsbSmartCardReaderIdentivUsbSmartCardReaderUsbSmartCardReaderManagerUsbSmartCardReaderOnSubscribeacsidentiveUsbDeviceUsbManagerBroadcastReceiverContextIntentIntentFilterNfcSmartCardReaderNfcSmartCardReaderManagerApduEncryptorTagIsoDepReaderCallbackObservableObservableEmitterObservableOnSubscribeActivityPendingIntentiosecurityutilutil \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3f2eb17..72cd184 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,6 @@ material = "1.13.0" mockitoCore = "5.20.0" navigationFragmentKtx = "2.9.5" recyclerview = "1.4.0" -rxjava = "3.1.12" truth = "1.4.5" [libraries] @@ -50,7 +49,6 @@ material = { group = "com.google.android.material", name = "material", version.r mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockitoCore" } navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigationFragmentKtx" } recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } -rxjava = { group = "io.reactivex.rxjava3", name = "rxjava", version.ref = "rxjava" } truth = { group = "com.google.truth", name = "truth", version.ref = "truth" } [plugins] diff --git a/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/IdemiaWithPace.java b/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/IdemiaWithPace.java index e4d81b9..3487c19 100644 --- a/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/IdemiaWithPace.java +++ b/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/IdemiaWithPace.java @@ -61,10 +61,10 @@ import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil; /** - * ID1WithPace extends ID1 APDU protocol with Secure Messaging and PACE capabilities + * IdemiaWithPace extends Idemia APDU protocol with Secure Messaging and PACE capabilities * enabling the use over NFC. It must implement the ApduEncryptor interface so that * NfcSmartCardReader class has an oracle to encrypt C-APDUs and decrypt R-APDUs - * so that the ID1 APDU protocol can remain mostly unchanged + * so that the Idemia APDU protocol can remain mostly unchanged * @noinspection FieldCanBeLocal, SameParameterValue */ class IdemiaWithPace extends Idemia implements TokenWithPace, ApduEncryptor { diff --git a/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/Token.java b/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/Token.java index dd76153..c2e8c5d 100644 --- a/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/Token.java +++ b/libs/id-card-lib/src/main/java/ee/ria/DigiDoc/idcard/Token.java @@ -19,20 +19,12 @@ package ee.ria.DigiDoc.idcard; -import org.bouncycastle.util.encoders.Hex; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import ee.ria.DigiDoc.smartcardreader.SmartCardReader; import ee.ria.DigiDoc.smartcardreader.SmartCardReaderException; -import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil; /** * EstEID token interface. */ public interface Token { - String TAG = Token.class.getName(); /** * Read personal information of the cardholder. @@ -125,30 +117,4 @@ byte[] authenticate(byte[] pin1, byte[] token) */ byte[] decrypt(byte[] pin1, byte[] data, boolean ecc) throws SmartCardReaderException; - /** - * Create an instance of Token based on the current card in the reader. - * - * @param reader Smart card reader instance, must be connected. - * @return Token instance. - * @throws SmartCardReaderException When card is not supported or reader is not connected. - */ - static Token create(SmartCardReader reader) throws SmartCardReaderException { - byte[] atr = reader.atr(); - LoggingUtil.Companion.debugLog(TAG, "ATR: " + (atr == null ? "null" : Hex.toHexString(atr)), null); - - if (atr == null) { - throw new SmartCardReaderException("ATR cannot be null"); - } - if (Arrays.equals(Hex.decode("3bdb960080b1fe451f830012233f536549440f9000f1"), atr)) { - return new Idemia(reader); - } else if (Arrays.equals(Hex.decode("3bdc960080b1fe451f830012233f54654944320f9000c3"), atr)) { - return new Idemia(reader); - } else if (Arrays.equals(Hex.decode("3bff9600008031fe438031b85365494464b085051012233f1d"), atr)) { - Thales thales = new Thales(reader); - thales.selectMainAid(); - return thales; - } - - throw new SmartCardReaderException("Unsupported card ATR: " + new String(Hex.encode(atr), StandardCharsets.UTF_8)); - } } diff --git a/libs/smart-card-reader-lib/build.gradle.kts b/libs/smart-card-reader-lib/build.gradle.kts index 81b170f..0a56232 100644 --- a/libs/smart-card-reader-lib/build.gradle.kts +++ b/libs/smart-card-reader-lib/build.gradle.kts @@ -18,24 +18,12 @@ android { lint { lintConfig = file("../lint.xml") } - - buildFeatures { - buildConfig = true - } } dependencies { implementation(libs.androidx.annotation) implementation(libs.bcprov.jdk18on) implementation(libs.guava) - implementation(libs.rxjava) - - implementation( - files( - "libs/acssmc-1.1.6.jar", // ACS - "libs/androidSCardV1.2.jar" // Identiv - ) - ) implementation(project(":libs:card-utils-lib")) diff --git a/libs/smart-card-reader-lib/libs/acssmc-1.1.6.jar b/libs/smart-card-reader-lib/libs/acssmc-1.1.6.jar deleted file mode 100644 index ee5252d..0000000 Binary files a/libs/smart-card-reader-lib/libs/acssmc-1.1.6.jar and /dev/null differ diff --git a/libs/smart-card-reader-lib/libs/androidSCardV1.2.jar b/libs/smart-card-reader-lib/libs/androidSCardV1.2.jar deleted file mode 100644 index 845c507..0000000 Binary files a/libs/smart-card-reader-lib/libs/androidSCardV1.2.jar and /dev/null differ diff --git a/libs/smart-card-reader-lib/src/main/AndroidManifest.xml b/libs/smart-card-reader-lib/src/main/AndroidManifest.xml index 735e97c..ec6d59e 100644 --- a/libs/smart-card-reader-lib/src/main/AndroidManifest.xml +++ b/libs/smart-card-reader-lib/src/main/AndroidManifest.xml @@ -1,9 +1,5 @@ - - diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/SmartCardReaderManager.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/SmartCardReaderManager.java deleted file mode 100644 index df3121e..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/SmartCardReaderManager.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader; - -import io.reactivex.rxjava3.core.Observable; - -public interface SmartCardReaderManager { - - Observable status(); - - SmartCardReader connectedReader() throws SmartCardReaderException; -} diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/SmartCardReaderStatus.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/SmartCardReaderStatus.java deleted file mode 100644 index 7705f75..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/SmartCardReaderStatus.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader; - -public enum SmartCardReaderStatus { - - /** - * No readers detected. - */ - IDLE, - - /** - * Supported reader detected and connected. - */ - READER_DETECTED, - - /** - * Card inside reader detected, ready to receive transmissions. - */ - CARD_DETECTED, -} diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/AcsUsbSmartCardReader.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/AcsUsbSmartCardReader.java deleted file mode 100644 index 8b639cb..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/AcsUsbSmartCardReader.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader.usb; - -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; - -import com.acs.smartcard.Reader; -import com.acs.smartcard.ReaderException; - -import java.util.Arrays; - -import ee.ria.DigiDoc.smartcardreader.SmartCardReaderException; -import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil; - -public final class AcsUsbSmartCardReader extends UsbSmartCardReader { - private static final String TAG = AcsUsbSmartCardReader.class.getName(); - private static final int SLOT = 0; - - private final Reader reader; - - public AcsUsbSmartCardReader(UsbManager usbManager) { - reader = new Reader(usbManager); - } - - @Override - public boolean supports(UsbDevice usbDevice) { - return reader.isSupported(usbDevice); - } - - @Override - public void open(UsbDevice usbDevice) { - reader.open(usbDevice); - } - - @Override - public void close() { - reader.close(); - } - - @Override - public boolean connected() { - if (reader.isOpened() && reader.getState(SLOT) == Reader.CARD_PRESENT) { - try { - reader.power(SLOT, Reader.CARD_WARM_RESET); - reader.setProtocol(SLOT, Reader.PROTOCOL_TX); - } catch (ReaderException e) { - LoggingUtil.Companion.errorLog(TAG, "Connecting to ACS reader exception: " + e.getMessage(), e); - } - } - return reader.isOpened() && reader.getState(SLOT) == Reader.CARD_SPECIFIC; - } - - @Override - public byte[] atr() { - return reader.getAtr(SLOT); - } - - @Override - protected byte[] transmit(byte[] apdu) throws SmartCardReaderException { - byte[] recv = new byte[1024]; - int len; - try { - len = reader.transmit(SLOT, apdu, apdu.length, recv, recv.length); - } catch (ReaderException e) { - throw new SmartCardReaderException(e); - } - return Arrays.copyOf(recv, len); - } -} diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/IdentivUsbSmartCardReader.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/IdentivUsbSmartCardReader.java deleted file mode 100644 index 552560e..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/IdentivUsbSmartCardReader.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader.usb; - -import static com.identive.libs.WinDefs.SCARD_LEAVE_CARD; -import static com.identive.libs.WinDefs.SCARD_PROTOCOL_TX; -import static com.identive.libs.WinDefs.SCARD_SHARE_EXCLUSIVE; -import static com.identive.libs.WinDefs.SCARD_SPECIFIC; - -import android.content.Context; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; - -import com.identive.libs.SCard; - -import java.util.ArrayList; -import java.util.Arrays; - -import ee.ria.DigiDoc.smartcardreader.SmartCardReaderException; - -public final class IdentivUsbSmartCardReader extends UsbSmartCardReader { - - private static final int VENDOR_ID = 1254; - - private final Context context; - private final UsbManager usbManager; - private final SCard sCard; - - public IdentivUsbSmartCardReader(Context context, UsbManager usbManager) { - this.context = context; - this.usbManager = usbManager; - sCard = new SCard(); - } - - @Override - public boolean supports(UsbDevice usbDevice) { - if (!usbManager.hasPermission(usbDevice) && usbDevice.getVendorId() == VENDOR_ID) { - return true; - } - open(usbDevice); - ArrayList readers = new ArrayList<>(); - sCard.SCardListReaders(context, readers); - return !readers.isEmpty(); - } - - @Override - public void open(UsbDevice usbDevice) { - sCard.SCardEstablishContext(context); - } - - @Override - public void close() { - sCard.SCardDisconnect(SCARD_LEAVE_CARD); - sCard.SCardReleaseContext(); - } - - @Override - public boolean connected() { - sCard.SCardEstablishContext(context); - - SCard.SCardState state = sCard.new SCardState(); - sCard.SCardStatus(state); - if (state.getnState() == SCARD_SPECIFIC) { - return true; - } - - ArrayList readers = new ArrayList<>(); - sCard.SCardListReaders(context, readers); - if (!readers.isEmpty()) { - sCard.SCardConnect(readers.get(0), SCARD_SHARE_EXCLUSIVE, (int) SCARD_PROTOCOL_TX); - } - return false; - } - - @Override - public byte[] atr() { - SCard.SCardState state = sCard.new SCardState(); - sCard.SCardStatus(state); - return Arrays.copyOf(state.getAbyATR(), state.getnATRlen()); - } - - @Override - protected byte[] transmit(byte[] apdu) throws SmartCardReaderException { - SCard.SCardIOBuffer io = sCard.new SCardIOBuffer(); - io.setAbyInBuffer(apdu); - io.setnInBufferSize(apdu.length); - io.setAbyOutBuffer(new byte[0x8000]); - io.setnOutBufferSize(0x8000); - sCard.SCardTransmit(io); - if (io.getnBytesReturned() == 0) { - throw new SmartCardReaderException("Failed to send apdu"); - } - String rstr = ""; - for (int k = 0; k < io.getnBytesReturned(); k++) { - int temp = io.getAbyOutBuffer()[k] & 0xFF; - if (temp < 16) { - rstr = rstr.toUpperCase() + "0" + Integer.toHexString(io.getAbyOutBuffer()[k]); - } else { - rstr = rstr.toUpperCase() + Integer.toHexString(temp); - } - } - return Arrays.copyOf(io.getAbyOutBuffer(), io.getnBytesReturned()); - } -} diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReader.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReader.java deleted file mode 100644 index d963d0a..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReader.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader.usb; - -import android.hardware.usb.UsbDevice; - -import ee.ria.DigiDoc.smartcardreader.SmartCardReader; - -/** - * Base class for smart card readers. - *

- * TODO Log all transmit commands in hex (request and response) - */ -public abstract class UsbSmartCardReader extends SmartCardReader { - - public abstract boolean supports(UsbDevice usbDevice); - - public abstract void open(UsbDevice usbDevice); - -} diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReaderManager.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReaderManager.java deleted file mode 100644 index db61368..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReaderManager.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader.usb; - -import android.content.Context; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; - -import androidx.annotation.Nullable; - -import com.google.common.collect.ImmutableList; - -import java.util.concurrent.TimeUnit; - -import ee.ria.DigiDoc.smartcardreader.SmartCardReader; -import ee.ria.DigiDoc.smartcardreader.SmartCardReaderException; -import ee.ria.DigiDoc.smartcardreader.SmartCardReaderStatus; -import ee.ria.DigiDoc.smartcardreader.SmartCardReaderManager; -import io.reactivex.rxjava3.core.Observable; - -/** - * Manage smart card readers on Android platform. - */ -public final class UsbSmartCardReaderManager implements SmartCardReaderManager { - - /** - * Card connected retry interval in milliseconds. - */ - private static final int CONNECT_RETRY = 2500; - - private final UsbManager usbManager; - private final ImmutableList readers; - - private final Observable statusObservable; - - private SmartCardReader reader; - - public UsbSmartCardReaderManager(Context context, UsbManager usbManager, - ImmutableList readers) { - this.usbManager = usbManager; - this.readers = readers; - statusObservable = Observable - .create(new UsbSmartCardReaderOnSubscribe(context, this)) - .switchMap(readerOptional -> { - if (readerOptional.isPresent()) { - return Observable - .fromCallable(() -> { - readerOptional.get().connected(); - return readerOptional; - }) - .repeatWhen(completed -> - completed.delay(CONNECT_RETRY, TimeUnit.MILLISECONDS)); - } else { - return Observable.just(readerOptional); - } - }) - .map(readerOptional -> { - if (!readerOptional.isPresent()) { - reader = null; - return SmartCardReaderStatus.IDLE; - } - reader = readerOptional.get(); - if (reader.connected()) { - return SmartCardReaderStatus.CARD_DETECTED; - } else { - return SmartCardReaderStatus.READER_DETECTED; - } - }) - .replay(1) - .refCount(); - } - - boolean supports(UsbDevice usbDevice) { - return reader(usbDevice) != null; - } - - @Nullable - SmartCardReader reader(UsbDevice usbDevice) { - for (UsbSmartCardReader reader : readers) { - if (reader.supports(usbDevice)) { - if (usbManager.hasPermission(usbDevice)) { - reader.open(usbDevice); - } - return reader; - } - } - return null; - } - - @Override - public Observable status() { - return statusObservable; - } - - @Override - public SmartCardReader connectedReader() throws SmartCardReaderException { - if (reader == null || !reader.connected()) { - throw new SmartCardReaderException("Reader or card is not connected"); - } - return reader; - } -} diff --git a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReaderOnSubscribe.java b/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReaderOnSubscribe.java deleted file mode 100644 index db7c152..0000000 --- a/libs/smart-card-reader-lib/src/main/java/ee/ria/DigiDoc/smartcardreader/usb/UsbSmartCardReaderOnSubscribe.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2017 - 2025 Riigi Infosüsteemi Amet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -package ee.ria.DigiDoc.smartcardreader.usb; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; -import android.os.Build; - -import androidx.annotation.Nullable; - -import com.google.common.base.Optional; - -import ee.ria.DigiDoc.smartcardreader.BuildConfig; -import ee.ria.DigiDoc.smartcardreader.SmartCardReader; -import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil; -import io.reactivex.rxjava3.core.ObservableEmitter; -import io.reactivex.rxjava3.core.ObservableOnSubscribe; - -final class UsbSmartCardReaderOnSubscribe implements ObservableOnSubscribe> { - private static final String TAG = UsbSmartCardReaderOnSubscribe.class.getName(); - private static final String ACTION_USB_DEVICE_PERMISSION = BuildConfig.LIBRARY_PACKAGE_NAME + - ".USB_DEVICE_PERMISSION"; - - private final Context context; - private final UsbManager usbManager; - private final UsbSmartCardReaderManager smartCardReaderManager; - - @Nullable private UsbDevice currentDevice; - @Nullable private SmartCardReader currentReader; - - UsbSmartCardReaderOnSubscribe(Context context, UsbSmartCardReaderManager smartCardReaderManager) { - this.context = context; - usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); - this.smartCardReaderManager = smartCardReaderManager; - } - - @Override - public void subscribe(ObservableEmitter> emitter) { - BroadcastReceiver deviceAttachReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - UsbDevice device = getUsbDevice(intent); - LoggingUtil.Companion.debugLog(TAG, String.format("Smart card device attached: %s", device), null); - if (device != null && smartCardReaderManager.supports(device)) { - requestPermission(device); - } - } - }; - BroadcastReceiver deviceDetachReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - UsbDevice device = getUsbDevice(intent); - LoggingUtil.Companion.debugLog(TAG, String.format("Smart card device detached: %s", device), null); - if (device != null && currentDevice != null && - currentDevice.getDeviceId() == device.getDeviceId()) { - clearCurrent(); - emitter.onNext(Optional.absent()); - } - } - }; - BroadcastReceiver devicePermissionReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - boolean permissionGranted = intent.getBooleanExtra( - UsbManager.EXTRA_PERMISSION_GRANTED, false); - UsbDevice device = getUsbDevice(intent); - LoggingUtil.Companion.debugLog(TAG, String.format("Smart card device permission: granted: %s; device: %s", permissionGranted, - device), null); - if (permissionGranted && smartCardReaderManager.supports(device)) { - clearCurrent(); - currentDevice = device; - currentReader = smartCardReaderManager.reader(device); - emitter.onNext(Optional.fromNullable(currentReader)); - } - } - }; - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - context.registerReceiver(deviceAttachReceiver, - new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED), Context.RECEIVER_NOT_EXPORTED); - context.registerReceiver(deviceDetachReceiver, - new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED), Context.RECEIVER_NOT_EXPORTED); - context.registerReceiver(devicePermissionReceiver, - new IntentFilter(ACTION_USB_DEVICE_PERMISSION), Context.RECEIVER_NOT_EXPORTED); - } else { - context.registerReceiver(deviceAttachReceiver, - new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED)); - context.registerReceiver(deviceDetachReceiver, - new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED)); - context.registerReceiver(devicePermissionReceiver, - new IntentFilter(ACTION_USB_DEVICE_PERMISSION)); - } - - emitter.setCancellable(() -> { - context.unregisterReceiver(deviceAttachReceiver); - context.unregisterReceiver(deviceDetachReceiver); - context.unregisterReceiver(devicePermissionReceiver); - clearCurrent(); - }); - - for (UsbDevice device : usbManager.getDeviceList().values()) { - if (smartCardReaderManager.supports(device)) { - requestPermission(device); - break; - } - } - } - - private void requestPermission(UsbDevice device) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - Intent permissionIntent = new Intent(ACTION_USB_DEVICE_PERMISSION); - permissionIntent.setPackage(context.getPackageName()); - - usbManager.requestPermission(device, - PendingIntent - .getBroadcast(context, 0, permissionIntent, PendingIntent.FLAG_MUTABLE)); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - usbManager.requestPermission(device, - PendingIntent - .getBroadcast(context, 0, new Intent(ACTION_USB_DEVICE_PERMISSION), PendingIntent.FLAG_MUTABLE)); - } else { - usbManager.requestPermission(device, - PendingIntent - .getBroadcast(context, 0, new Intent(ACTION_USB_DEVICE_PERMISSION), 0)); - } - } - - private void clearCurrent() { - currentDevice = null; - if (currentReader != null) { - try { - currentReader.close(); - } catch (Exception e) { - LoggingUtil.Companion.errorLog(TAG, String.format("Closing current reader %s", currentReader), e); - } - currentReader = null; - } - } - - private UsbDevice getUsbDevice(Intent intent) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { - return intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice.class); - } else { - return intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - } - } -} diff --git a/libs/smart-card-reader-lib/src/test/java/ee/ria/DigiDoc/smartcardreader/UsbSmartCardReaderTest.java b/libs/smart-card-reader-lib/src/test/java/ee/ria/DigiDoc/smartcardreader/UsbSmartCardReaderTest.java deleted file mode 100644 index 4af35e4..0000000 --- a/libs/smart-card-reader-lib/src/test/java/ee/ria/DigiDoc/smartcardreader/UsbSmartCardReaderTest.java +++ /dev/null @@ -1,740 +0,0 @@ -package ee.ria.DigiDoc.smartcardreader; - -import static com.google.common.truth.Truth.assertThat; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mock; -import org.mockito.MockMakers; - -import ee.ria.DigiDoc.smartcardreader.usb.UsbSmartCardReader; - -@SuppressWarnings("ResultOfMethodCallIgnored") -public final class UsbSmartCardReaderTest { - - @Rule public final ExpectedException exception = ExpectedException.none(); - - @Mock(mockMaker = MockMakers.SUBCLASS) - private SmartCardReader usbSmartCardReader; - - @Before - public void before() throws Exception { - usbSmartCardReader = mock(UsbSmartCardReader.class, withSettings().mockMaker(MockMakers.SUBCLASS)); - when(usbSmartCardReader.transmit(any())) - .thenReturn(new byte[] {(byte) 0x90, 0x00}); - } - - @Test - public void transmit_dataNull_leNull() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, null, null); - - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03}); - } - - @Test - public void transmit_dataEmpty_leNull() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[0], null); - - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03}); - } - - @Test - public void transmit_data255Bytes_leNull() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04}, null); - - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04}); - } - - @Test - public void transmit_data510Bytes_leNull() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}, null); - - verify(usbSmartCardReader).transmit(new byte[] {0x10, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04}); - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}); - } - - @Test - public void transmit_data700Bytes_leNull() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}, null); - - verify(usbSmartCardReader).transmit(new byte[] {0x10, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04}); - verify(usbSmartCardReader).transmit(new byte[] {0x10, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}); - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, (byte) 0xBE, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}); - } - - @Test - public void transmit_dataNull_lePresent() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, null, 0x00); - - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, 0x00}); - } - - @Test - public void transmit_data255Bytes_lePresent() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04}, 0x00); - - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, - 0x00}); - } - - @Test - public void transmit_data510Bytes_lePresent() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}, 0x01); - - verify(usbSmartCardReader).transmit(new byte[] {0x10, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, - 0x01}); - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x01}); - } - - @Test - public void transmit_data700Bytes_lePresent() throws Exception { - usbSmartCardReader.transmit(0x00, 0x01, 0x02, 0x03, new byte[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}, 0x03); - - verify(usbSmartCardReader).transmit(new byte[] {0x10, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, - 0x03}); - verify(usbSmartCardReader).transmit(new byte[] {0x10, 0x01, 0x02, 0x03, (byte) 0xFF, - 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x03}); - verify(usbSmartCardReader).transmit(new byte[] {0x00, 0x01, 0x02, 0x03, (byte) 0xBE, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x03}); - } - - @Test - public void transmit_response9000() throws Exception { - when(usbSmartCardReader.transmit(any())) - .thenReturn(new byte[] {(byte) 0x90, 0x00}); - - assertThat(usbSmartCardReader.transmit(0x00, 0x00, 0x00, 0x00, null, null)) - .isEqualTo(new byte[0]); - } - - @Test - public void transmit_responseDataAnd9000() throws Exception { - when(usbSmartCardReader.transmit(any())) - .thenReturn(new byte[] {0x01, 0x03, 0x05, (byte) 0x90, 0x00}); - - assertThat(usbSmartCardReader.transmit(0x00, 0x00, 0x00, 0x00, null, null)) - .isEqualTo(new byte[] {0x01, 0x03, 0x05}); - } - - @Test - public void transmit_responseDataAnd61XX() throws Exception { - when(usbSmartCardReader.transmit(any())) - .thenReturn( - new byte[] {0x01, 0x03, 0x05, 0x61, 0x05}, - new byte[] {0x05, 0x04, 0x03, 0x02, 0x01, (byte) 0x90, 0x00}); - - assertThat(usbSmartCardReader.transmit(0x00, 0x00, 0x00, 0x00, null, null)) - .isEqualTo(new byte[] {0x01, 0x03, 0x05, 0x05, 0x04, 0x03, 0x02, 0x01}); - } - - @Test - public void transmit_responseDataNot9000Nor61XX() throws Exception { - when(usbSmartCardReader.transmit(any())) - .thenReturn(new byte[] {0x67, 0x69}); - - exception.expect(equalTo(new ApduResponseException((byte) 0x67, (byte) 0x69))); - - usbSmartCardReader.transmit(0x00, 0x00, 0x00, 0x00, null, null); - } -}