晴耕雨読

working in the fields on fine days and reading books on rainy days

APDUコマンドの返り値をメッセージで表示する

ICカードへAPDUコマンドを送信すると、必ず2バイトの返り値が得られます。 その値の意味をメッセージで表示することでデバッグなどの作業が捗るので、APDUレスポンスの一覧と、その一部の意味を表示するPythonコードを紹介します。

Pythonで定義した関数 get_status_msg(sw1, sw2) は引数1に1バイト目の値、引数2に2バイト目の値を渡すと、値の意味を文字列で返す関数です。 全てのレスポンスを拾うと巨大な関数になってしまうので重要そうなメッセージだけを表示するようにしています。 pyscardと一緒に使用する例を以下に示します。

from smartcard.util import toHexString
from smartcard.System import readers as get_readers
readers = get_readers()
print(readers)

conn = readers[0].createConnection()
conn.connect()

send_data = [0xFF, 0xCA, 0x00, 0x00, 0x00]
recv_data, sw1, sw2 = conn.transmit(send_data)

def get_status_msg(sw1, sw2):
    if sw1 == 0x90 and sw2 == 0x00:
        return "I: 正常終了"
    if sw1 == 0x61:
        return f"I: 出力成功。残り{int(sw2)}バイトが出力可能です。"
    if sw1 == 0x62:
        if sw2 == 0x81: return "W: 出力データに異常があります。"
        if sw2 == 0x83: return "W: 選択したファイルは無効になりました。"
        return "W: 不揮発性メモリの状態は変更されていません。"
    if sw1 == 0x63:
        if sw2 == 0x81: return "W: ファイルの書き込み可能領域が不足しています。"
        if (sw2 >> 4) == 0xc: return f"W: 検証失敗。残り{int(sw2 & 0x0f)}回リトライ可能です。"
        return "W: 不揮発性メモリの状態は変化しています。"
    if sw1 == 0x64:
        if sw2 == 0x01: return "E: コマンドはタイムアウトしました。"
        return "E: 不揮発性メモリの状態は変更されていません。"
    if sw1 == 0x65:
        if sw2 == 0x01: return "E: 書き込みエラーが発生しました。"
        return "E: 不揮発性メモリの状態は変化しています。"
    if sw1 == 0x66:
        if sw2 == 0x00: return "E: 受信時にタイムアウトエラーが発生しました。"
        if sw2 == 0x01: return "E: 受信時にパリティチェックエラーが発生しました。"
        if sw2 == 0x02: return "E: 受信時にチェックサムエラーが発生しました。"
        if sw2 == 0x69: return "E: 不正な暗号化/復号パディングが含まれています。"
        return "E: セキュリティエラーが発生しました。"
    if sw1 == 0x67:
        if sw2 == 0x00: return "E: データ長(Lc/Leフィールド)が不正です。"
        return "E: データ長が不正です。"
    if sw1 == 0x68:
        return "E: CLAの機能は対応していません。"
    if sw1 == 0x69:
        if sw2 == 0x81: return "E: ファイル構造と互換性のないコマンドです。"
        if sw2 == 0x82: return "E: セキュリティ条件が満たされていません。"
        if sw2 == 0x83: return "E: 認証方法がブロックされています。"
        if sw2 == 0x84: return "E: 参照データがブロックされました。"
        if sw2 == 0x85: return "E: コマンドの使用条件を満たしていません。"
        if sw2 == 0x86: return "E: ファイルが存在しません。"
        if sw2 == 0x87: return "E: セキュアメッセージングに必要なデータオブジェクトが存在しません。"
        if sw2 == 0x88: return "E: セキュアメッセージングのデータオブジェクトが不正です。"
        return "E: コマンドは許可されていません。"
    if sw1 == 0x6a:
        if sw2 == 0x80: return "E: データフィールドのパラメータが正しくないです。"
        if sw2 == 0x81: return "E: サポートされていない機能です。"
        if sw2 == 0x82: return "E: ファイルが存在しません。"
        if sw2 == 0x83: return "E: レコードが存在しません。"
        if sw2 == 0x84: return "E: レコードまたはファイルのメモリ容量が不足しています。"
        if sw2 == 0x85: return "E: LcはTLV構造と一致しません。"
        if sw2 == 0x86: return "E: P1またはP2パラメータが正しくありません。"
        if sw2 == 0x87: return "E: LcがP1-P2と一致しない。"
        if sw2 == 0x88: return "E: 参照データが見つかりません。"
        if sw2 == 0x89: return "E: ファイルが既に存在します。"
        if sw2 == 0x8A: return "E: DF名が既に存在します。"
        return "E: パラメータの値が間違っています。"
    if sw1 == 0x6b:
        return "E: パラメータの値が間違っています。"
    if sw1 == 0x6d:
        return "E: 命令コード(INS)が不正です。"
    if sw1 == 0x6e:
        return "E: 命令クラス(CLA)が不正です。"
    if sw1 == 0x6f:
        return "E: 内部エラーが発生しました。"
    return ""

print(get_status_msg(sw1, sw2))
print(toHexString(recv_data))

以下おまけ

APDUレスポンス一覧

種類は3個あり、それぞれ I: 情報(Infomation)、W: 警告(Warning)、E: エラー(Error) です。

SW1 SW2 種類 内容
6- E クラスはサポートされていません。
61 I 応答バイトはまだ利用可能
61 XX I コマンドは正常に実行されました。「XX」バイトのデータが使用可能であり、GETRESPONSEを使用して要求できます。
62 W 不揮発性メモリの状態は変更されていません
62 00 W 情報が提供されていません(NV-Ramは変更されていません)
62 01 W NV-RAMは変更されていません。
62 81 W 返されたデータの一部が破損している可能性があります
62 82 W Leバイトを読み取る前にファイル/レコードの終わりに達しました
62 83 W 選択したファイルが無効になりました
62 84 W 選択したファイルが無効です。FCIがISOに従ってフォーマットされていない
62 85 W カードのセンサーから利用できる入力データがありません。R3bc用にスレーブされた財布エンジンはありません
62 A2 W 間違ったR-MAC
62 A4 W カードがロックされています(reset中)
62 CX W 値xのカウンター(コマンドに依存)
62 F1 W 間違ったC-MAC
62 F3 W 内部リセット
62 F5 W デフォルトのエージェントがロックされています
62 F7 W カード所有者がロックされています
62 F8 W 地下室は現在のエージェントです
62 F9 W CALCキーセットのブロックが解除されていません
62 FX W
62 XX W RFU
63 W 不揮発性メモリの状態が変更されました
63 00 W 情報が提供されていません(NV-Ramが変更されました)
63 81 W 最後の書き込みでいっぱいになったファイル。ロード/更新は許可されていません。
63 82 W カードキーはサポートされていません。
63 83 W リーダーキーはサポートされていません。
63 84 W プレーンテキスト送信はサポートされていません。
63 85 W セキュアな送信はサポートされていません。
63 86 W 揮発性メモリは使用できません。
63 87 W 不揮発性メモリは使用できません。
63 88 W キー番号が無効です。
63 89 W キーの長さが正しくありません。
63 C0 W 失敗を確認します。残りはありません。
63 C1 W 失敗を確認し、残り1回試行します。
63 C2 W 失敗を確認し、残り2回試行します。
63 C3 W 失敗を確認し、残り3回試行します。
63 CX W カウンターが値 'x'(0 = x = 15)に達しました(コマンドによって異なります)。
63 F1 W より多くのデータが期待されます。
63 F2 W より多くのデータが予想され、プロアクティブなコマンドが保留中です。
63 FX W
63 XX W RFU
64 E 不揮発性メモリの状態は変更されていません
64 00 E 情報が提供されていません(NV-Ramは変更されていません)
64 01 E コマンドタイムアウト。カードに必要な即時応答。
64 XX E RFU
65 E 不揮発性メモリの状態が変更されました
65 00 E 情報がありません
65 01 E 書き込みエラー。メモリ障害。EEPROMの書き込みまたは読み取りに問題がありました。他のハードウェアの問題もこのエラーを引き起こす可能性があります。
65 81 E メモリ障害
65 FX E
65 XX E RFU
66 S  
66 00 S 受信中のエラー(タイムアウト)
66 01 S 受信中のエラー(文字パリティエラー)
66 02 S 間違ったチェックサム
66 03 S FCIのない現在のDFファイル
66 04 S 現在のDFの下にSFまたはKFはありません
66 69 S 暗号化/復号化のパディングが正しくない
66 XX S
67 E  
67 00 E 間違った長さ
67 XX E 長さが正しくない(手順)(ISO7816-3)
68 E CLAの機能はサポートされていません
68 00 E 情報がありません(リクエスト機能はカードでサポートされていません)
68 81 E 論理チャネルはサポートされていません
68 82 E 安全なメッセージングは​​サポートされていません
68 83 E チェーンの最後のコマンドが必要です
68 84 E コマンドチェーンはサポートされていません
68 FX E
68 XX E RFU
69 E コマンドは許可されていません
69 00 E 情報が提供されていません(コマンドは許可されていません)
69 01 E コマンドは受け入れられません(非アクティブ状態)
69 81 E コマンドはファイル構造と互換性がありません
69 82 E セキュリティ条件が満たされていません。
69 83 E 認証方法がブロックされました
69 84 E 参照データは可逆的にブロック(無効化)されました
69 85 E 使用条件が満たされていません。
69 86 E コマンドは許可されていません(現在のEFはありません)
69 87 E 予期されるセキュアメッセージング(SM)オブジェクトがありません
69 88 E 不正なセキュアメッセージング(SM)データオブジェクト
69 8D   予約済み
69 96 E データを再度更新する必要があります
69 E1 E 現在有効なプロファイルのPOL1は、このアクションを防ぎます。
69 F0 E アクセス拒否
69 F1 E 許可が拒否されました–特権がありません
69 FX E
69 XX E RFU
6A E 間違ったパラメータP1-P2
6A 00 E 情報が提供されていません(バイトP1および/またはP2が正しくありません)
6A 80 E データフィールドのパラメータが正しくありません。
6A 81 E 機能はサポートされていません
6A 82 E ファイルが見つかりません
6A 83 E 記録が見当たりませんでした
6A 84 E レコードまたはファイルに十分なメモリスペースがありません
6A 85 E LcがTLV構造と矛盾している
6A 86 E P1またはP2パラメータが正しくありません。
6A 87 E LcがP1-P2と矛盾している
6A 88 E 参照データが見つかりません
6A 89 E ファイルが既に存在します
6A 8A E DF名はすでに存在します。
6A F0 E パラメータ値が間違っています
6A FX E
6A XX E RFU
6B E  
6B 00 E 間違ったパラメータP1-P2
6B XX E 参照が正しくありません(プロシージャバイト)(ISO 7816-3)
6C E 間違った長さのル
6C 00 E P3の長さが正しくありません。
6C XX E Leの長さの値が正しくありません。「xx」は正しい正確なLeです
6D E  
6D 00 E 命令コードがサポートされていないか無効です
6D XX E 命令コードがプログラムされていないか無効です(プロシージャバイト)、(ISO 7816-3)
6E E  
6E 00 E クラスはサポートされていません
6E XX E 命令クラスはサポートされていません(プロシージャバイト)、(ISO 7816-3)
6F E 内部例外
6F 00 E コマンドが中止されました – より正確な診断は不可能です(オペレーティングシステムエラーなど)。
6F FF E カードが死んでいる(使いすぎなど)
6F XX E 正確な診断なし(手順バイト)、(ISO 7816-3)
9- 00    
90 00 I コマンドは正常に実行されました(OK)。
90 04 W PINが正常に確認されなかった、3回以上のPINの試行が残っている
90 08   キー/ファイルが見つかりません
90 80 W ブロック解除試行カウンターがゼロに達しました
91 00   OK
91 01   States.activity、States.lock Status、またはStates.lockableの値が間違っています
91 02   トランザクション数が制限に達しました
91 0C   変更なし
91 0E   コマンドを完了するにはNVメモリが不足しています
91 1C   コマンドコードはサポートされていません
91 1E   CRCまたはMACがデータと一致しません
91 40   無効なキー番号が指定されました
91 7E   コマンド文字列の長さが無効です
91 9D   要求されたコマンドを許可しない
91 9E   パラメータの値が無効です
91 A0   要求されたAIDがPICCに存在しません
91 A1   アプリケーション内の回復不能なエラー
91 AE   認証ステータスが要求されたコマンドを許可していません
91 AF   追加のデータフレームが送信される予定です
91 BE   境界外
91 C1   PICC内の回復不能なエラー
91 CA   前のコマンドが完全に完了していません
91 CD   回復不能なエラーによりPICCが無効になりました
91 CE   アプリケーションの数は28に制限されています
91 DE   ファイルまたはアプリケーションはすでに存在します
91 EE   電力損失のため、NV書き込み操作を完了できませんでした
91 F0   指定されたファイル番号が存在しません
91 F1   ファイル内の回復不能なエラー
92 0x I 'x'の試行後、EEPROMへの書き込みは成功しました。
92 10 E 不十分なメモリ。利用可能なストレージはこれ以上ありません。
92 40 E EEPROMへの書き込みが失敗しました。
93 01   整合性エラー
93 02   候補S2が無効
93 03 E アプリケーションは永続的にロックされています
94 00 E EFが選択されていません。
94 01   補通貨コードが財布の通貨と一致しません
94 02   補量が多すぎます
94 02 E アドレス範囲を超えました。
94 03   候補量が少なすぎる
94 04 E FIDが見つからない、レコードが見つからない、または比較パターンが見つかりません。
94 05   データフィールドの問題
94 06 E 必要なMACが利用できません
94 07   悪い通貨:財布エンジンにはR3bc通貨のスロットがありません
94 08   R3bc通貨は財布エンジンではサポートされていません
94 08 E 選択したファイルタイプがコマンドと一致しません。
95 80   シーケンスが悪い
96 81   スレーブが見つかりません
97 00   PINがブロックされ、ブロック解除試行カウンターが1または2
97 02   メインキーがブロックされています
97 04   PINが正常に確認されなかったが、3回以上のPINの試行が残っている
97 84   ベースキー
97 85   制限を超えました – C-MAC鍵
97 86   SMエラー – 制限を超えました – R-MAC鍵
97 87   制限を超えました – シーケンスカウンター
97 88   制限を超えました – R-MACの長さ
97 89   サービスは利用できません
98 02 E PINが定義されていません。
98 04 E アクセス条件が満たされていないため、認証に失敗しました。
98 35 E ASKRANDOMまたはGIVERANDOMが実行されていません。
98 40 E PINの確認に失敗しました。
98 50 E 制限に達したため、INCREASEまたはDECREASEを実行できませんでした。
98 62 E 認証エラー、アプリケーション固有(MACが正しくない)
99 00   1PINを残してみてください
99 04   PINが正常に確認されていません、1つのPINを残してください
99 85   間違ったステータス – カード所有者のロック
99 86 E 特権がありません
99 87   PINがインストールされていません
99 88   間違ったステータス – R-MAC状態
9A 00   2PIN左を試す
9A 04   PINが正常に確認されていません、2PINを残してみてください
9A 71   間違ったパラメーター値 – 二重スパイAID
9A 72   間違ったパラメータ値 – 二重スパイタイプ
9D 05 E 証明書の種類が正しくありません
9D 07 E 不正なセッションデータサイズ
9D 08 E DIRファイルのレコードサイズが正しくありません
9D 09 E FCIレコードサイズが正しくありません
9D 0A E コードサイズが正しくありません
9D 10 E アプリケーションをロードするためのメモリが不足しています
9D 11 E 無効なAID
9D 12 E 重複するAID
9D 13 E 以前にロードされたアプリケーション
9D 14 E アプリケーション履歴リストがいっぱい
9D 15 E アプリケーションが開いていません
9D 17 E 無効なオフセット
9D 18 E アプリケーションはすでにロードされています
9D 19 E 無効な証明書
9D 1A E 無効な署名
9D 1B E 無効なKTU
9D 1D E MSMコントロールが設定されていません
9D 1E E アプリケーションの署名が存在しません
9D 1F E KTUは存在しません
9D 20 E アプリケーションがロードされていません
9D 21 E オープンコマンドのデータ長が無効です
9D 30 E データパラメータが正しくないことを確認してください(開始アドレスが無効です)
9D 31 E データパラメータが正しくないことを確認してください(長さが無効です)
9D 32 E チェックデータパラメータが正しくありません(不正なメモリチェック領域)
9D 40 E 無効なMSMコントロール暗号文
9D 41 E MSMコントロールはすでに設定されています
9D 42 E MSMコントロールのデータ長を2バイト未満に設定します
9D 43 E 無効なMSMコントロールのデータ長
9D 44 E 過剰なMSMは暗号文を制御します
9D 45 E MSMコントロールデータの検証に失敗しました
9D 50 E MCD発行者のプロダクションIDが無効です
9D 51 E 無効なMCD発行者ID
9D 52 E 無効なセットMSMはデータ日付を制御します
9D 53 E 無効なMCD番号
9D 54 E 予約フィールドエラー
9D 55 E 予約フィールドエラー
9D 56 E 予約フィールドエラー
9D 57 E 予約フィールドエラー
9D 60 E MAC検証に失敗しました
9D 61 E 到達したブロック解除の最大数
9D 62 E カードはブロックされませんでした
9D 63 E 暗号機能は利用できません
9D 64 E アプリケーションがロードされていません
9E 00   PINがインストールされていません
9E 04   PINが正常に検証されていない、PINがインストールされていない
9F 00   PINがブロックされ、ブロック解除試行カウンターが3
9F 04   PINが正常に検証されず、PINがブロックされ、ブロック解除試行カウンターが3
9F XX   コマンドは正常に実行されました。'xx'バイトのデータが使用可能であり、GETRESPONSEを使用して要求できます。
9X XX   アプリケーション関連のステータス、(ISO 7816-3)

参考文献