
ISO7816のハードウェアサポートを備えたプロセッサ(たとえばSTM32F4xx )について話していることをすぐに言わなければなりません。ソフトウェアエミュレーターの作成は依然として熱狂的です。これは、非常に強く押すか、 余暇が多すぎる場合に発生します。
結論と配線図
では、入り口には何がありますか? 次のような3ボルトの石とISO7816-2形式のカード :


- VCC-電源
- RST-入力をリセット
- I / O-双方向データライン
- CLK-クロッキング
- GND-アース
- VPP-プログラミング出力
VCC入力には3つのオプションがあります:1.8 V、3 V、5 V(それぞれカードクラスA、B、C)、 RSTはカードのステートマシンをリセットする機能(アクティブレベルが低い)、 I / Oはデータライン、これは通常のUARTであり 、 CLKはカードのプロセッサのクロックに使用されます(カードが非アクティブである場合、周波数はそれぞれ供給されません)、 VPPピンはカードのプログラムに使用されます。
これが、実際のハッカーがカードを接続する方法です。

インターフェース
インターフェイスはUSARTドライバーの同期モードです。つまり、情報の各ビットの送信をCLKピンの周波数と同期しますが、他の同期インターフェイス(同じSPIなど )とは1つの重要な違いがあります。 CLKおよび372パルス(このマジックナンバーはISO7816の 3つの部分で記述され、 ETU (Elementary Time Unit)と呼ばれます)、つまり、1データビットが372番目(理想的な場合)のフロントごとにクロックされます。 周波数自体は1〜5 MHzの範囲にある必要があります。
それでは、データ行( I / O ) を扱いましょう。 先ほど言ったように、これは次のパラメーターを持つ通常のUARTです。
- データビット: 8
- ストップビット: 1.5
- パービット: 偶数(偶数)
- 速度(開始時): 9600ボー
原則として、このインターフェースのハードウェアプロパティについてこれ以上知る必要はありません。 それでは、ドライバーのセットアップに移りましょう。
ドライバーのセットアップ
ここで、 標準周辺機器ライブラリで書かれた初期化コードをすぐに投げます:
RCC_ClocksTypeDef RCC_Clocks; USART_InitTypeDef USART_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; NVIC_InitTypeDef NVIC_InitStructure; /// RCC_GetClocksFreq(&RCC_Clocks); /// SC_USART_APB_PERIPH_CLOCK(RCC_APB2Periph_USART1, ENABLE); /// USART_SetPrescaler(USART1, (RCC_Clocks.PCLK2_Frequency / CLK_FREQ) / 2); /// Guard Time USART_SetGuardTime(USART1, 16); /// ( CLK) USART_ClockInitStructure.USART_Clock = USART_Clock_Enable; USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; USART_ClockInitStructure.USART_CPHA = USART_CPHA_1Edge; USART_ClockInitStructure.USART_LastBit = USART_LastBit_Enable; USART_ClockInit(USART1, &USART_ClockInitStructure); /// ( I/O) USART_InitStructure.USART_BaudRate = CLK_FREQ / ETU; USART_InitStructure.USART_WordLength = USART_WordLength_9b; USART_InitStructure.USART_StopBits = USART_StopBits_1_5; USART_InitStructure.USART_Parity = USART_Parity_Even; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_InitStructure); /// NACK USART_SmartCardNACKCmd(USART1, ENABLE); /// - USART_SmartCardCmd(USART1, ENABLE); /// USART_Cmd(USART1, ENABLE); /// 2 ( ) USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_PE, ENABLE); /// NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
コードが乱雑にならないように出力設定を下げましたが、1つの重要なポイントがあります。I / O出力はOpen-Drainとして構成する必要があります。標準では、カード自体がどこでプルするかを決定するときにZ状態のラインを見つける可能性があるためです。
ここでは、2つのポイント(分周前と為替レート)に焦点を当てたいと思います。 ここでの問題は何ですか? 一方では、速度を9600に設定する必要があり、他方では、システム速度の周波数倍数に設定する必要があります。
おそらく、ほとんどの場合、超低電力が不要な場合、システム周波数は最大(私の場合は168 MHz)に選択され、使用するUSARTモジュールはAPB2バスからクロックされます。その最大周波数は84 MHzであり、選択する周波数は下がるはずです1〜5 MHzの範囲で84 MHzの倍数ですが、9600の速度の場合、周波数は9600 * 372 = 3.5712 MHzになります。 ここにいる方法は? 規格の開発者はこの瞬間を提供し、公称値から最大20%の偏差を設定したため、3.5 MHzなどの周波数を静かに丸め、3500000/372 = 9409の速度を選択できます。ここでの差異は2%未満ですこれはまったく問題ありません。 除算器の値を2で割る必要があります(つまり、値1は2、2-4、3-6などによる除算に対応します)。 (84 / 3,5)/ 2 = 12を取得します:
- 周波数( CLK ):3.5 MHz
- 速度( I / O ):9409ボー
- プリスクレーア:12
さらに、私が検討したいのは、パリティエラーの処理です。 これを行うために、 ガードタイムと呼ばれる特別に用意された時間間隔があります(この国では16ビットです)。 ガードタイムとは? ガードタイムは、パリティエラー( NACK )の場合にレシーバがI / Oラインに低レベルを設定する必要がある時間間隔であり、トランスミッタはこれに同じフレームを再度送信する必要があります。 この機能の有用性については特に説明しませんが、純粋に私の意見では、原則としてそのようなエラーが存在する場合、交換チャネルは信頼できないと見なされる可能性があり、そのような手段はここでは役立ちそうにありません。
ドライバーの設定では、すべてが明確であると思うので、カードとの交換を初期化するプロセスに移りましょう。
スタート
カードを開始するには、「コールド」リセットを実行する必要があります。 次のシーケンスを表します。
- RSTロー
- VCCの電源を入れます
- 周波数をCLKに送信
- 40,000 CLKサイクルの時間間隔を待ちます
- RSTハイ
- 40,000サイクルの応答を待ちます

すべてが単純で、リセットを実行し、応答を待ちます。 応答の最初のビットが40,000サイクル(t3)以内に到着しなかった場合、 RSTを Lowに設定し、 I / OおよびCLKを非アクティブにする必要があります。
ATR
この応答は何ですか? ATR (Answer-to-Reset)は次の構造です(各フィールドのサイズは1バイトです):
- TS:頭文字
- TO:フォーマット文字
- TAi:インターフェース文字[コードFI、DI]
- TBi:インターフェース文字[コードII、PI1]
- TCi:インターフェース文字[コードN]
- TDi:インターフェース文字[コードYi + 1、T]
- T1、...、TK:歴史的キャラクター(最大15)
- TCK:チェックキャラクター
1. TSは開始バイトです。 次の2つの値のいずれかを取ることができます:3Fhおよび3Bh:
- 3Fh-逆変換-逆極性、つまり 0は高く送信され、1-低は送信されます(重要なポイント、奇数はパリティを制御するためにここで使用されます、つまり奇数):
- 3Bh-直接の慣習-直接の極性-同じ、しかしまったく反対(パリティ-偶数、つまり偶数)
2. T0 フォーマットバイト 。 2オクテットで構成されます。
- Y1(高オクテット)は、続くフィールドを示すビットマスクです。
- b5-TA1が送信されます
- b6-TB1が送信されます
- b7-TC1が送信されます
- b8-TD1が送信されます
- K(低オクテット)-「履歴」バイトの数

3. TA1 。 周波数調整のパラメーターが含まれます。
- FI(高オクテット)-配当
- DI(低オクテット)-除数

4. TB1 。 VPP出力特性が含まれます:
- II(ビットb7-b6)-最大プログラミング電流
- PI(ビットb5-b1)-プログラミング電圧

5. TC1 。 パラメーターNが含まれます- ガード時間の追加増分( ETU単位で設定)、0から254の値を取ることができ、255の値は、2つの隣接するフレームの最初のエッジ間の間隔が11 ETUに減少することを意味します。
6. TD1 ISO7816ではこのバイトの構造が明らかにされていないため、少し混乱がありますが、すべてがソースでかなりインテリジェントに記述されています[1]。 2オクテットで構成されます。
- Y2(高オクテット)は、続くフィールドを示すビットマスクです。
- b5-TA2が送信されます
- b6-TB2が送信されます
- b7-送信されたTC2
- b8-TD2が送信されます
- T(低オクテット)-使用されるプロトコル(0-T0、1-T1、その他の値は予約済み)

7. TA2 。 有効ビットが1つ(最上位)のみ含まれ、プロトコルの別のバージョンへの切り替えの可能性を示します(0-切り替えは可能、1-切り替えは不可能)、バイトが送信されない場合、0と等しいと見なされます

8. T1、...、TKは履歴バイトです。 カードに関する情報、発行者、発行日時などが含まれます。このフィールドの形式は規格によって規制されていません
9. TCK- チェックサムバイト 。 これは、前のすべてのバイトのモジュロ2(xor)加算によって計算されます(T1プロトコルにのみ存在)
ここで何が必要かを理解してみましょう。 フィールドTA1およびTA2に最も関心があり、どのアクションをとるべきか、つまり、2つのモードのいずれかを選択する必要があることを示しています。
- 交渉モード
- 特定のモード
最上位ビットがTA2 = 0の場合、「ネゴシエーション」モードを使用します。それ以外の場合は、指定されたモードを使用します。
Pts
ネゴシエートされた交換は、 PTS (プロトコルタイプ選択)と呼ばれるプロセスです。 このプロセスでは、ペアリングデバイスに、新しい設定を適用する準備ができたことをカードに伝えるシーケンスを送信します。 次に、カードは同じシーケンスで応答する必要があります。その後、カードとペアリングデバイスの両方が新しい設定で作業を開始できます。 適用する設定については、 ATRフレームのバイトTA1が通知されます。 パラメータFiとDiは値そのものではなく、テーブル内の数値です。 表から、これらの数値に対応する値F (クロックレート変換係数)およびD (ビットレート調整係数)を見つけることができます。
Fi-Fテーブル。
FI | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
F | 内部クロック | 372 | 558 | 744 | 1116 | 1488 | 1860 | RFU |
FI | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
F | RFU | 512 | 768 | 1024 | 1536 | 2048 | RFU | RFU |
テーブルDi-D。
DI | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
D | RFU | 1 | 2 | 4 | 8 | 16 | RFU | RFU |
DI | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
D | RFU | RFU | 1/2 | 1/4 | 1/8 | 1/16 | 1/32 | 1/64 |
* RFU-将来の使用のために予約済み
FとDの除算の商は、新しいETU値です。 任意の周波数と速度を選択できますが、それらの比率は特定のF / Dに等しくなければならないことを考慮してください。
PTSフレーム自体の詳細:
- PTSS:初期文字(必須)
- PTS0:フォーマット文字(必須)
- PTS1(オプション)
- PTS2(オプション)
- PTS3(オプション)
- PCK:チェックキャラクター(必須)
1. PTSS- 開始バイト (常にFFh)
2. PTS0- フォーマットバイト 。 フレームに存在するフィールドを決定します;最も重要なオクテットはビットマスクです:
- b5-PTS1が送信されます
- b6-PTS2が送信されます
- b7-PTS3が送信されています
- b8-常に0、予約済み
- T(低オクテット)-使用されるプロトコル(0-T0、1-T1、その他の値は予約済み)

3. PTS1 。 バイトTA1 ATRで受信したFiとDiの要求値が含まれます。バイトが送信されない場合、 FiとDiは1に等しいと見なされます。

4. PTS2 。 TC1 ATRで指定されたパラメーターNが適用されるかどうかを示します。
5. PTS3 。 予約済み。
6. PCK- チェックサムバイト 。 これは、前のすべてのバイトのモジュロ2(xor)加算によって計算されます。
簡単です。シーケンスを作成し、送信し、回答を待ち、比較し、一致する場合は、速度をFclk /( F / D )に再構築します。
カードが「ネゴシエーション」モードをサポートしていない場合、作業を続行します。
例
材料を統合するために、簡単な例を作成してみます。 これは通常のBeeline SIMカードです。 彼女が投げるATRは次のとおりです。
3B 3B 94 00 9B 44 20 10 4D AD 40 00 33 90 00 3Bh(TS)-直接コンベンション 3Bh(T0)(0011 1011)-「歴史的」バイト数= 11であるTA1およびTB1を想定 94h(TA1)-Fi = 9、Di = 4、テーブル1と2に従ってFとDを見つける(F = 512、D = 8)、新しいETU = 512/8 = 64 00h(TB1)-VPPはサポートされていません
この場合、PTSフレームは次のようになります。
FF 10 94 7B FFh(PTSS)-初期バイト 10h(PTS0)(0001 0000)-PTS0、プロトコルT0を送信 94h(PTS1)= TA1 7Bh(PCK)= xor(FF 10 94)
結論
私の記事では、スマートカードのプログラミングなどの詳細を省略し、チャネルおよびアプリケーション層のプロトコルも考慮しませんでしたが、これにはいくつかの理由があります。 第一に、これらの各項目は個別の記事に基づいていますが、それ以上ではありません。第二に、私の意見では、インターネット上のAPDUプロトコルに関する情報がたくさんあります。
まあ、私は私の仕事が気付かれることなく、または少なくとも苦しんでいる人の好奇心を満たさないことを本当に願っています。 とにかく、マスターしたすべての人のおかげで、私は質問に答えて、横棒のためにいくつかの他のキックを得ることができてうれしいです。 最後に、 暗号化Javaマップに関する素晴らしい一連の記事を読むことを強くお勧めします 。 すべてに良い!
リンク集
- http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816.aspx-実際には、標準自体
- http://www.hackersrussia.ru/Cards/ASyncro/ISO7816-3.phpロシア語のISO7816
- http://www.st.com/web/en/resource/technical/document/application_note/CD00166510.pdf-STM32F10xのアプリケーションノート
- http://www.smartcard.co.uk/tutorials/sct-itsc.pdf-優れたスマートカードチュートリアル