OmapiTest.testTransmitApdu()が期待するSIMカードの振る舞い(2)
前回は、Android Secure Element CTSのOmapiTest.testTransmitApdu()を、Pythonスクリプトで再現するところまで。今回は、それに対応するJava Cardアプレット側の実装を行います。
cheerio-the-bear.hatenablog.com
その前に「インストール」できないことに気付く
前々回、ほぼ空っぽのJava Cardアプレットを「ロード」してみましたが、その次のステップ「インストール」に失敗することに気付きました。
cheerio-the-bear.hatenablog.com
やはりSIMツールキット用のアプレットじゃないと駄目なんだろうかとか、試行錯誤していて気付きました。どうやら、モジュールAIDとインスタンスAIDが一致していないといけないようです。仕様的にはその限りではないものと理解しているのですが、一致していればインストールできるので、ひとまず気にしないで走り抜けることにします。
ということで、ちょっとしたコードの掃除と一緒に、Makefileを更新して各種AIDを変更しました。
ロード、インストールおよび削除のコマンドは、この時点ではこうです。
- ロード
- python shadysim.py --pcsc -l ./cardlet.cap --kic 9A665E9CDA096DAE9C04894785EB0B18 --kid 1A8DD88431450CAF8D3719F6380F0A18
- インストール
- python shadysim.py --pcsc -i ./cardlet.cap --module-aid A000000476416E64726F696443545331 --instance-aid A000000476416E64726F696443545331 --nonvolatile-memory-required 0100 --volatile-memory-for-install 0300 --kic 9A665E9CDA096DAE9C04894785EB0B18 --kid 1A8DD88431450CAF8D3719F6380F0A18
- 削除
- python shadysim.py --pcsc -d A00000047600 --kic 9A665E9CDA096DAE9C04894785EB0B18 --kid 1A8DD88431450CAF8D3719F6380F0A18
UnicodeDecodeError: 'charmap' codec can't decodeとは
このUnicodeDecodeErrorには、地味に足踏みさせられました。どうやらsmartcardのSCardGetErrorMessage()には「あるある」なエラーらしく、なんでもWindowsが日本語でエラーを返していて、それをうまくデコードできないんだとか。
$ python sects.py ... C-APDU : 010C000001AA Traceback (most recent call last): File "sects.py", line 176, in <module> omapi.execute_all() File "sects.py", line 159, in execute_all self.testTransmitApdu() File "sects.py", line 121, in testTransmitApdu (response, sw) = self.commandif.send_apdu(selectable_aid, apdu) File "sects.py", line 85, in send_apdu (response, sw) = self.send_apdu_on_channel(channel_number, apdu) File "sects.py", line 74, in send_apdu_on_channel (response, sw) = self.transport.send_apdu(apdu) File "C:\Users\cheeriotb\projects\osmocom3\osmocom-sim-tools\shadysim\pySim\transport\__init__.py", line 68, in send_apdu data, sw = self.send_apdu_raw(pdu) File "C:\Users\cheeriotb\projects\osmocom3\osmocom-sim-tools\shadysim\pySim\transport\pcsc.py", line 79, in send_apdu_raw data, sw1, sw2 = self._con.transmit(apdu) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\CardConnectionDecorator.py", line 82, in transmit return self.component.transmit(bytes, protocol) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\CardConnection.py", line 146, in transmit data, sw1, sw2 = self.doTransmit(bytes, protocol) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\pcsc\PCSCCardConnection.py", line 205, in doTransmit SCardGetErrorMessage(hresult)) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\scard\scard.py", line 1278, in SCardGetErrorMessage return _scard.SCardGetErrorMessage(lErrCode) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\encodings\cp1250.py", line 15, in decode return codecs.charmap_decode(input,errors,decoding_table) UnicodeDecodeError: 'charmap' codec can't decode byte 0x83 in position 0: character maps to <undefined>
ちゃんとコードで言語設定を合わせる方法があるんじゃないかとしばらく探していたのですが、そもそも本筋ではないところに長く時間を費やすのは得策ではなく。ひとまず、PCの言語設定を英語にして回避。カードへのデータの送信に問題があったことがわかりました。
$ python sects.py ... C-APDU : 010C000001AA00 Traceback (most recent call last): File "sects.py", line 175, in <module> omapi.execute_all() File "sects.py", line 158, in execute_all self.testTransmitApdu() File "sects.py", line 149, in testTransmitApdu (response, sw) = self.commandif.send_apdu(selectable_aid, apdu) File "sects.py", line 85, in send_apdu (response, sw) = self.send_apdu_on_channel(channel_number, apdu) File "sects.py", line 74, in send_apdu_on_channel (response, sw) = self.transport.send_apdu(apdu) File "C:\Users\cheeriotb\projects\osmocom3\osmocom-sim-tools\shadysim\pySim\transport\__init__.py", line 68, in send_apdu data, sw = self.send_apdu_raw(pdu) File "C:\Users\cheeriotb\projects\osmocom3\osmocom-sim-tools\shadysim\pySim\transport\pcsc.py", line 79, in send_apdu_raw data, sw1, sw2 = self._con.transmit(apdu) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\CardConnectionDecorator.py", line 82, in transmit return self.component.transmit(bytes, protocol) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\CardConnection.py", line 146, in transmit data, sw1, sw2 = self.doTransmit(bytes, protocol) File "C:\Users\cheeriotb\AppData\Local\Programs\Python\Python37\lib\site-packages\smartcard\pcsc\PCSCCardConnection.py", line 205, in doTransmit SCardGetErrorMessage(hresult)) smartcard.Exceptions.CardConnectionException: Failed to transmit with protocol T0. A communications error with the smart card has been detected. Retry the operation.
CardConnectionException: Failed to transmit with protocol T0の原因
カードへのデータ送信に問題があったのは、単純にJava Cardアプレット側が未完成だったためです。APDU.setOutgoing()のAPI仕様には、下記のようにノートが付けられていました。なるほど、確かにそのときにはまだsetIncomingAndReceive()を呼んでいませんでしたし、カードがデータを受信する前に送信しようとするコードになっていましたので、このエラーには納得です。
Notes.
On a case 4 command, the setIncomingAndReceive() must be invoked prior to calling this method. Otherwise, erroneous behavior may result in T=0 protocol.
ということで、Java Card側の実装を追加してOmapiTest.testTransmitApdu()に耐えられるようになりました。
テストを実行した際の、APDUコマンドのやり取りがこれです。それらしく動作しています。
$ python sects.py ... started: testTransmitApdu C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 01060000 R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 81060000 R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : A1060000 R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 95060000 R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 010A000001AA R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 810A000001AA R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : A10A000001AA R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 950A000001AA R-APDU + SW : 9000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 0108000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 8108000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : A108000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 9508000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 010C000001AA00 R-APDU + SW : 9f00 C-APDU : 01c0000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 810C000001AA00 R-APDU + SW : 9f00 C-APDU : 81c0000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : A10C000001AA00 R-APDU + SW : 9f00 C-APDU : A1c0000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 C-APDU : 0070000001 R-APDU + SW : 019000 C-APDU : 01A4040010A000000476416E64726F69644354533100 R-APDU + SW : 9f0c C-APDU : 01c000000c R-APDU + SW : 6f0a640353010162038501019000 C-APDU : 950C000001AA00 R-APDU + SW : 9f00 C-APDU : 95c0000000 R-APDU + SW : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000 C-APDU : 00708001 R-APDU + SW : 9000 finished: testTransmitApdu
いい感じです。次のテストに取り掛かってみましょう。