SyntaxHighlighter

2017年6月24日土曜日

最近ちょっとFelicaにハマっている

最近ちょっとFelicaにハマっている。

Felicaで色々するのが流行ったのは2008年ごろだろうか。
当時自分も、Felicalibを使ってIDmを読み込んで認証するプログラムを作った覚えがある。
その時、RC-S330を購入したのも覚えていた。

最近、といっても1年ほど前だろうか。
ふとしたことで、NFC搭載のSDカードを手に入れた。
東芝のアレだ。

当時自分はNFCを読み取れる機材がなく、SDカードも別に不足していなかったので、
戸棚にしまったままになっていた。

3月頃、ふとAndroidアプリ開発をしたくなってNexus5Xを購入していた。
NFC読み取り機能もあることだし、と、免許証や電子マネーの読み取りアプリも入れていた。

それで、ふと先のNFC-SDカードを思い出した。
Nexsus5Xにアプリを入れ読み取ると、ちょっと使いづらいながらも
無事サムネイルとカード名を読めるようになった。

NFC-Type Fなので、PC+PaSoRiでも読めそうだが、公式にはないし、
やっている人も見かけない。

ここでふと思った。ざっと探してもネット上でこのSDカードを解析している人はいない。
しかし、自分は前にFelicalibで少しだがFelicaには触っている。
ちょっと調べれば実は簡単にできるのではないか?と。

実際、このSDカードの仕様とメモリマップは公開されていた。
見た感じ結構単純そうであるし、行けるだろう、と思ったのが罠だった。

詳細はFlashAir開発者向け非公式wikiを参照してほしい。
http://seesaawiki.jp/flashair-dev/d/NFC%3aPC%a4%ab%a4%e9%c6%c9%a4%df%bd%d0%a4%b9
のだが、ここでもかいつまんで説明しよう。

まず、Felicaには現在最低でも2種類ある。
Felica Standard: これは、いわゆるSuica等の普通の高セキュリティなFelicaだ。
 いわゆるカード型Felicaのそれは全部これである。
Felica Lite: これは機能が省略された安価なFelicaで、そのかわり小型省電力。
 もともとNFC用に作られたと言ってもいいもので、ポスターやフィギュア、
 シールや小さなカードなど、小型軽量薄い、そして安いが、
 暗号化機能はごっそり削られ、容量もかなり少ない
 一部では会員証として普通のFelicaと同じカードの形をしていることもある。

で、2008年ごろのFelicaといえば、Felica Standardのことだった。
Felica Liteはあとから出てきたもので、いわゆるNFCはほぼこっちである。

そう、2008年で更新が止まっているFelicalibはFelica Standard用に作られており
一方、NFC SDカードは、NFCの名の通りFelica Liteなのである。

Felica Standardは、かなり複雑な階層構造になっており、
システム→サービス→エリア→データブロックになっている。
”システム”でEdyやSuicaなどが別れ、そのシステムも共有の領域な場合があって
そこはサービスで分ける。(Edyなどは共有領域を使っている)
そして、サービスの中はエリアで別れていて...と言った感じ。
(エリアは8階層まで可能らしい)
なので、ディレクトリ構造になる。
またこれらを扱うために多種多様なコマンドがある。
アクセス手法もランダムや、サイクリック、パースなどあるし、暗号化も様々できる。
トランザクション処理もできる。

一方、Felica Liteは、システムもサービスもエリアもない
ブロックしかない。ブロックしかない。
そのため、ブロックアドレスのマップ、メモリマップで全てが表せる。
さらに、コストカットのためコマンドも削られている。
・ポーリング
・暗号化なし読み取り
・暗号化なし書き込み
しかない。

ただ、互換のためシステムコードは0x88B4(Felica Lite) or 0x12FC(NDEF)で反応し、
サービスも0x0009(読み書き可)と0x000B(読み取り専用)がある。
(2つのサービスは同じ1つの領域を読み書きする。権限が違うだけである)

...であることから、通常Felica Standardで使われる普通の手順
1. ポーリングする
2. システム一覧を取得
3. システムの中のサービス一覧を取得
4. サービスの中のエリア・ブロックにアクセス
が成立しない。

もう2も3も成立しない。

そのため、Felica Standardで使われるダンププログラムを使うと、
謎の00領域00サービスの山に悩まされることになる。
(実際にはコマンドエラーで失敗していると思われる)

一方、単純故に解決も簡単で
1. 0x88B4で決め打ちポーリングする
2. サービスは0x000B固定で、エリアも無視して、ブロックアドレス与えて単に読み書きする
に愚直に従えば良い。

良いのだが、ここでまたFelica Standardで現れなかったのであろう問題がぶつかった。
Felicalibが1バイトアドレスにしか対応していなかった。

そもそも、Felica Standardは細分化された構造にデータが置かれているから、
そんなに1つの領域に大量にデータを置くことがなかったのだろう。

一方、Felica Liteは1つの領域しかないため、そこに置くしかない。
そのため1バイトで表せるアドレス数では足りなかった。
(※本当のFelica Liteは足ります。Felica Plug等の外部メモリがついているタイプのが困るのです)

Felicaには2バイトアドレスでアクセスする方法が予め用意されていたので、
それでアクセスすれば問題なし...なのだが、ライブラリにはその機能がなかった。

そのため、改造が必要になった。
ちなみに、改造したライブラリはここにあります。
https://sites.google.com/site/gpsnmeajp/tools/felicalib_segfix
エラー対処や、いろいろな改善(改悪含め)が入ってます。

んで、読み書きできればこちらのもの。
あとはメモリマップに従ってやれば、読み出しできる。

Felicaなんで、標準242kbps、高速424bpsしかないけど。
さらに1ブロック単位アクセスをするとなお遅い。

おそーい。

それでも読み出すツールはできましたので、こちらに置いておきます。
https://sites.google.com/site/gpsnmeajp/tools/nfcsddumper
同梱されているライブラリは最低限の改造しかしていないものですので、
プログラムに組み込んで使うのであればこちらではなく、上のを使ってください


0 件のコメント:

コメントを投稿