STM32。 ISO7816規格のスマートカードを接続します

スマートカードについては多くのことが言われていますが、最近まで物理レベルでカードとやり取りするプロセスは謎のままでした。 私の記事では、 ISO7816標準のパート3で説明されているインターフェイスを使用してスマートカードを操作する問題を強調したいと思います。 情報の抽出に多くの時間を費やしたことは正直に認めますが、すべてが非常にシンプルであることがわかりました。 興味があれば、猫の下に来てください。





ISO7816のハードウェアサポートを備えたプロセッサ(たとえばSTM32F4xx )について話しいることをすぐに言わなければなりません。ソフトウェアエミュレーターの作成は依然として熱狂的です。これは、非常に強く押すか、 余暇が多すぎる場合に発生します。


結論と配線図



では、入り口には何がありますか? 次のような3ボルトの石とISO7816-2形式のカード





  1. VCC-電源
  2. RST-入力をリセット
  3. I / O-双方向データライン
  4. CLK-クロッキング
  5. GND-アース
  6. 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です。



  1. データビット: 8
  2. ストップビット: 1.5
  3. パービット: 偶数(偶数)
  4. 速度(開始時): 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を取得します:





さらに、私が検討したいのは、パリティエラーの処理です。 これを行うために、 ガードタイムと呼ばれる特別に用意された時間間隔があります(この国では16ビットです)。 ガードタイムとは? ガードタイムは、パリティエラー( NACK )の場合にレシーバがI / Oラインに低レベルを設定する必要がある時間間隔であり、トランスミッタはこれに同じフレームを再度送信する必要があります。 この機能の有用性については特に説明しませんが、純粋に私の意見では、原則としてそのようなエラーが存在する場合、交換チャネルは信頼できないと見なされる可能性があり、そのような手段はここでは役立ちそうにありません。



ドライバーの設定では、すべてが明確であると思うので、カードとの交換を初期化するプロセスに移りましょう。



スタート



カードを開始するには、「コールド」リセットを実行する必要があります。 次のシーケンスを表します。



  1. RSTロー
  2. VCCの電源を入れます
  3. 周波数をCLKに送信
  4. 40,000 CLKサイクルの時間間隔を待ちます
  5. RSTハイ
  6. 40,000サイクルの応答を待ちます








すべてが単純で、リセットを実行し、応答を待ちます。 応答の最初のビットが40,000サイクル(t3)以内に到着しなかった場合、 RSTを Lowに設定し、 I / OおよびCLKを非アクティブする必要があります。



ATR



この応答は何ですか? ATR (Answer-to-Reset)は次の構造です(各フィールドのサイズは1バイトです):





1. TS開始バイトです。 次の2つの値のいずれかを取ることができます:3Fhおよび3Bh:





2. T0 フォーマットバイト 。 2オクテットで構成されます。





3. TA1 。 周波数調整のパラメーターが含まれます。





4. TB1 。 VPP出力特性が含まれます:





5. TC1 。 パラメーターNが含まれます- ガード時間の追加増分( ETU単位で設定)、0から254の値を取ることができ、255の値は、2つの隣接するフレームの最初のエッジ間の間隔が11 ETUに減少することを意味します。



6. TD1 ISO7816ではこのバイトの構造が明らかにされていないため、少し混乱がありますが、すべてがソースでかなりインテリジェントに記述されています[1]。 2オクテットで構成されます。





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



8. T1、...、TK履歴バイトです。 カードに関する情報、発行者、発行日時などが含まれます。このフィールドの形式は規格によって規制されていません



9. TCK- チェックサムバイト 。 これは、前のすべてのバイトのモジュロ2(xor)加算によって計算されます(T1プロトコルにのみ存在)



ここで何が必要かを理解してみましょう。 フィールドTA1およびTA2に最も関心があり、どのアクションをとるべきか、つまり、2つのモードのいずれかを選択する必要があることを示しています。



最上位ビットがTA2 = 0の場合、「ネゴシエーション」モードを使用します。それ以外の場合は、指定されたモードを使用します。



Pts



ネゴシエートされた交換は、 PTS (プロトコルタイプ選択)と呼ばれるプロセスです。 このプロセスでは、ペアリングデバイスに、新しい設定を適用する準備ができたことをカードに伝えるシーケンスを送信します。 次に、カードは同じシーケンスで応答する必要があります。その後、カードとペアリングデバイスの両方が新しい設定で作業を開始できます。 適用する設定については、 ATRフレームのバイトTA1通知されます。 パラメータFiDiは値そのものではなく、テーブル内の数値です。 表から、これらの数値に対応する値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-将来の使用のために予約済み



FDの除算の商は、新しいETU値です。 任意の周波数と速度を選択できますが、それらの比率は特定のF / Dに等しくなければならないことを考慮してください



PTSフレーム自体の詳細:





1. PTSS- 開始バイト (常にFFh)

2. PTS0- フォーマットバイト 。 フレームに存在するフィールドを決定します;最も重要なオクテットはビットマスクです:





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



4. PTS2TC1 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マップに関する素晴らしい一連の記事を読むことを強くお勧めします 。 すべてに良い!



リンク集






All Articles