LoginSignup
5
3

More than 5 years have passed since last update.

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

Posted at

はじめに

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

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3