2012/01/14

[mifare]Mifare Ultralightに書き込めるか?

Qtをやる、といっておきながら、ちょっと気になることが残っていた。
SDK for NFC starter Kitのサンプルに、Mifare Ultralightへの読み込みサンプルはついていた。
では、書き込みはどうやるのだろうか?
週末なので、調べておこう。
すべての解釈は「私が知っている範囲で」という一文が省略されているものと考えておくれ。

Mifareは種類がたくさんある。
Wikipedia(日本語)では、以下となっている。これは規格的な見方になるか。
  • Mifare Standard
  • Mifare T=CL
  • Mifare DESFire
  • Mifare DESFire8
  • Mifare Plus
本家Wikipedia(英語)では、こうなっている。これは製品ということになるか。
記載が充実している。
  • Mifare Classic
  • Mifare Ultralight
  • Mifare Ultralight C
  • Mifare DESFire
  • Mifare DESFire EV1
  • Mifare Plus
  • Mifare SAM AV2
mifare.netの歴史では、以下となっている。
  • Mifare Classic 1k
  • Mifare Pro
  • Mifare ProX
  • Mifare Ultralight
  • SmartMX
  • Mifare Classic 4k
  • Mifare DESFire
  • Mifare DESFireSAM
  • Mifare DESFire EV1
  • Mifare Ultralight C
  • Mifare Plus
  • Mifare SAM AV2
ざっと見通したい場合は、英語版Wikipediaの項目がよくまとまっていると思った。



私の手元にあるのは、Mifare Classic 1kとMifare Ultralight。
この2種類は、ISO14443規格とは微妙に外れているらしい。
外れているというか、暗号化に関してはNXP独自のもの、と書かれている。
Ultralightは、Classicのセキュリティ部分(と、ちょっと異なるコマンド)が除外されている、とある。
なので、UltralightはほぼISO14443規格に沿っているということであろう。
SDK for NFC Starter KitがUltralightだけになっているのも、そのあたりの事情であろう。
これをFeliCaにあててみると、Mifare Classic = FeliCa Standard、Mifare Ultralight = FeliCa Lite、という構図になろうか。



では、R/Wの立場からClassicとUltralightを見てみよう。
カードの見分け方は、SENS_RES(ATQA)とSEL_RES(SAK)で行う。
取得は、InListPassiveTargetコマンドを使う。送信するのは、SENS_REQ。
そうするとSENS_RESに、SENS_RES、SEL_RES、NFCID1(UID)が戻ってくる。
カードの種類だけであれば、SEL_RESを見るとよい。
どうやって見分けるかという情報は、NFC Forumドキュメントにはなく、NXPの以下を読む必要があろう。
http://www.nxp.com/documents/application_note/130830.pdf
これのp.7に、SAKの各ビットがもつ意味をフローチャートで記載してある。
なお、LSBは「bit1」になっているので要注意だ。ISO14443のドキュメントがそうなっているらしい。
全ビットに意味があるのであれば値一致で判別できそうなのだが、意味がよくわからないのでフローチャート通りに確認していくしかなさそうだ。
とりあえず、表にしてみた。「-」のところはN/Aだ。
b7 b6 b5 b4 b3 b2 b1 b0 Result
- - - - - - 1 - RFU
- - - 1 1 - 0 - Mifare 4K
- - - 0 1 - 0 0 Mifare 1K
- - - 0 1 - 0 1 Mifare Mini
- - 0 0 0 - 0 - Mifare Ultralight
- - 1 0 0 - 0 - ISO14443-4(RATS+PSS)
- - - 1 0 - 0 0 Mifare Plus 2K SL2
- - - - 0 - 0 1 Mifare Plus 4K SL2
ISO14443-3対応かどうかだけみたいのであれば、bit5だけ見ればよい(p.6参照)。
bit5、というのは、ドキュメントで言うところの「bit6」ね。
SENS_REQというのはNFC Forumでの名前なので、ISO14443では別の名前なのかも(REQA ?)。
SENS_RESやSEL_RESはNFC Forumでの名前で、ATQAやSAKはNXPドキュメントに書かれている名称だ。

では、ようやく本題のUltralightを見ていこう。
カードの仕様は、以下のドキュメントに記載されている。
http://www.classic.nxp.com/acrobat_download2/other/identification/M028634_MF0ICU1_Functional_Spec_V3.4.pdf
サポートしているコマンドは、以下。
  • REQA(0x26)
  • WUPA(0x52)
  • Anticollision CL1(0x93)
  • Select CL1(0x93)
  • Anticollision CL2(0x95)
  • Select CL2(0x95)
  • Read(0x30)
  • Halt(0x50)
  • Write(0xa2)
  • Compatibility write(0xa0)
NFC ForumのType2 Tagでは、以下のコマンドになっている。
  • READ(0x30)
  • WRITE(0xa2)
  • SECTOR SELECT(0xc2)
0xc2 ?
Ultralightのコマンドにないのであせったが、SECTOR SELECTは1KBずつに分けられたセクタを選択するコマンドのようだ。
Ultralightは64byteなので、コマンドが不要ということだろう。
書き込みコマンドが2種類ある。
0xa2と0xa0。
NFC Forumは0xa2。
0xa0の方は過去との互換用か何からしく、引数に16byte指定できるものの書き込まれるのは最初の4byteだけらしい。
なので、使うコマンドは0xa2でよかろう。
よく見ると、Writeコマンド0xa2も4byteしかデータが渡せない。
メモリマップを見ると、4byte×16ページ=64byteなのだった。
そのうち2ページはシリアル番号(UID)で、もう2ページもLockとかOTPとかで使われている。
実際に使えるページは12ページで、48byte分みたいだな。
(LockとOTPもユーザエリアとして使用できるとあるが、意味を持っているのでね。)
注意点としては、Writeはレスポンスを返さない、ということかな。

というわけで、SDK for NFC Starter Kitでのサンプルを作成。

githubにも置いた。
https://github.com/hirokuma/NfcStarterKitWrap/tree/master/UltralightReadWrite
ラッパがだんだん充実してきたので、作るのが楽になってきた。
タイムアウト時間などを調整したり、アクセスする部分を別スレッドに移動させたりするとアプリ的にはいいんだろうけどね。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。