Posted at

ACR1251にAndroid端末を乗せるとFeliCaカードと認識される問題を解決する


はじめに

NFCに興味を持ったので、Androidに搭載されているHost-based Card Emulation機能でなにかしてみようかなと思った。

ハローワールド的なものを作り終わって、さあ動かしてみようとACR1251CL-NTTComに乗せてみたら、TypeA/TypeBカードじゃなくてFeliCaと認識されてしまって、なんかうまく動かない!

という問題の解決を目指します。

この現象は、ちょっと型番忘れちゃったんですがAQUOS Phoneの何かで発生しました。

手持ちのXperiaZ/Z3/XZでは起きていません。

※ただ、XperiaはFeliCaとして認識されてほしい場合は困るかもしれません。TypeBカードとして認識されるので。

※しかしXperiaZ/Z3/XZはNFC-Fに対応してないので、FeliCaとしてACR1251に乗せたい場面が少ないかもしれません。


結論

ACR1251に「E0h 00h 00h 20h 01h 13h」のバイト列を送ると、設定が変わってFeliCaに反応しなくなります。

「E0h 00h 00h 20h 01h 1Fh」を送ると元に戻ります。


何が起きているのか

PCSCのWindCard系APIを使ってNFCカードを触っていると、ATR(Answer To Reset)という値を取得できます。

こいつが、Android端末を乗せたときに「僕FeliCaカードだよー」と叫びます。

具体的には下みたいな値が返ってきます。

3B-8F-80-01-80-4F-0C-A0-00-00-03-06-11-00-3B-00-00-00-00-42

まんなかちょっと後ろのほうに00-3Bと書いてありますが、これがFeliCaカードの証です。

今回は、こうなって欲しくありません。

詳細は不明ですが、なんとなく日本仕様なのかなと思います。


設定変更で解決

http://www.acs-japan.jp/products/258/acr1251-nfc のダウンロードページ最下部にApplication Programming InterfaceというPDFがあります。

これがACR1251の仕様書でして、この中のセクション5.4.12. Set PICC Operating Parameterに書いてあるコマンドを送信することで、反応するカードを選択することができます。

仕様に沿って、FeliCaのみ反応しないように設定すると「E0h 00h 00h 20h 01h 13h」です。

元に戻すには、すべてに反応する「E0h 00h 00h 20h 01h 1Fh」です。


ソースコード全文

ということで、設定変更のソースコード全文は以下です。

前半部分はeternalwindowsさんからお借りしました。(元ネタは参照セクションで)

ありがとうございます。

Visual Studio 2017 15.8.9で動くことを確認しています。

#include <windows.h>

#include <winscard.h>
#include <iostream>

#pragma comment (lib, "winscard.lib")

#define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500)

int main()
{
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
LPTSTR lpszReaderName;
LONG lResult;
DWORD dwAutoAllocate = SCARD_AUTOALLOCATE;
DWORD dwActiveProtocol;
BYTE bGetFirmwareCommand[] = { 0xE0, 0x00, 0x00, 0x20, 0x01, 0x13 };
BYTE bOutBuffer[256] = { 0 };
DWORD dwOutBufferLen = 0;

lResult = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hContext);
if (lResult != SCARD_S_SUCCESS) {
if (lResult == SCARD_E_NO_SERVICE)
MessageBox(NULL, TEXT("Smart Cardサービスが起動されていません。"), NULL, MB_ICONWARNING);
return 0;
}

lResult = SCardListReaders(hContext, SCARD_ALL_READERS, (LPTSTR)&lpszReaderName, &dwAutoAllocate);
if (lResult != SCARD_S_SUCCESS) {
if (lResult == SCARD_E_NO_READERS_AVAILABLE)
MessageBox(NULL, TEXT("カードリーダが接続されていません。"), NULL, MB_ICONWARNING);
return 0;
}

lResult = SCardConnect(hContext, lpszReaderName, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_UNDEFINED,&hCard, &dwActiveProtocol);
if (lResult !=
SCARD_S_SUCCESS) {
MessageBox(NULL, TEXT("カードリーダへの接続に失敗しました。"), NULL, MB_ICONWARNING);
return 0;
}

lResult = SCardControl(hCard, IOCTL_CCID_ESCAPE_SCARD_CTL_CODE, bGetFirmwareCommand,sizeof(bGetFirmwareCommand), bOutBuffer, sizeof(bOutBuffer), &dwOutBufferLen);
if (lResult != SCARD_S_SUCCESS) {
MessageBox(NULL, TEXT("カードリーダへの送信が失敗しました。"), NULL, MB_ICONWARNING);
return 0;
}

SCardDisconnect(hCard, SCARD_LEAVE_CARD);
SCardFreeMemory(hContext, lpszReaderName);
SCardReleaseContext(hContext);

return 0;
}


最後に

TypeAだけ、TypeBだけ、FeliCaだけに、それぞれ反応するように設定を変えると、

今使っているXperia XZだと以下みたいなATRが返ってきます。

TypeA

3B-80-80-01-01

TypeB

3B-F5-91-00-FF-91-81-71-FE-40-00-42-00-01-00-71-76

FeliCa

3B-8F-80-01-80-4F-0C-A0-00-00-03-06-11-00-3B-00-00-00-00-42

みなさんも、設定を変えてLet's HCE Life!!


参照

http://eternalwindows.jp/security/scard/scard02.html

https://tipszone.jp/20140902_introduction-to-nfc/

http://www.acs-japan.jp/products/258/acr1251-nfc