I want to exchange (or only read) the NFC tag ID from one Android device to another but I don't know if I should use peer-to-peer mode or emulate an NFC tag with HCE.
If I use HCE, is the emulated tag ID unique?
What is the better option or is there a simpler one?
Neither P2P nor HCE will provide you a unique ID, least not on any phone I'm aware of. With P2P it's required that the ID exchanged in ATR is random. With HCE the emulated tag ID is usually set to 08h plus a random number. There may be API call to set but I'm not aware of such. But it makes a lot of sense that a phone can not be uniquely identified by just anyone reading.
How can I read the NFC ID of another Android device?
I assume you are talking about the anti-collision identifier/UID here. On the reading Android device, you can use the reader-mode API to access devices in HCE mode:
nfcAdapter.enableReaderMode(this, new NfcAdapter.ReaderCallback() {
public void onTagDiscovered (Tag tag) {
byte[] uid = tag.getId();
// TODO: do something with the UID ...
}
}, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null);
Is the emulated tag ID unique?
See Stephen's answer. Typically, neither P2P mode nor HCE should provide a unique and stable ID. However, there are some exceptions to this and the point of time when a non-stable ID changes may vary (also see this answer). It could be that:
The device has a secure element and uses the static UID of that secure element.
The device generates a new random UID whenever it is turned on, but continues to use the same UID until it is powered off.
The device generates a new random UID on every activation by an external reader device. I.e. whenever an external HF field is applied to the NFC antenna of the Android device.
Also note that some NFC devices will use randomly generated UIDs that do not start with the random-prefix 0x08.
Can I force a device to use a fixed/stable UID?
Android does not provide an API to influence the UID/anti-collision identifier, so the short answer is no. However, if rooting or creating a custom ROM is an option, there are some possibilities to change the UID and other protocol parameters:
Editing Functionality of Host Card Emulation in Android
Host-based Card Emulation with Fixed Card ID
Should you use the UID to identify (or even authenticate) a device?
No, you should definitely not do this. While you sometimes do not have much choice when you try to integrate a HCE device into some legacy system, you should definitely think about a different design.
First of all, as Stephen already wrote, if an NFC device exposes a fixed/stable identifier, this could possibly introduce a privacy issue as anyone could read and track the ID.
Second, while many systems still use these IDs to authenticate(!) cards, UIDs are not necessarily unique (particularly there are less 4-byte UIDs than cards out there) and UIDs can easily be cloned. See this answer for further details.
Related
SIM card is used as a secure element in my project. It is accessed through NFC-SWP contactless interface from a terminal device.
I need to identify the SIM card somehow with a unique and permanent identifier and I need to be able to read the identifier through NFC. ICCID seems to be the best choice, but I would have to expose the EF ICCID file through the contactless interface, which might be dangerous. Moreover, the EF ICCID file is out of my scope on SIM card - access to my dedicated security domain is all I have.
I also tried to use the 4-byte long UID specified in ISO/IEC 14443 Type A, but I get a different UID each time I read the SIM card through NFC. Why?
Another solution would be accessing the card serial number through Global Platform Get Data command (Card Production Life Cycle Data (CPLC)), but I would have to be able to select the card manager through contactless interface, which is forbidden by default and not recommended because of security.
Is there any typical way to solve this issue?
The 4 byte UID for type A (same for PUPI for type B) is allowed to be random (ISO 14443-3, chap. 6.4.4 "fixed unique number or random number"). Their purpose is only, to select one of several cards currently in the field of the reader. Therefore the description of UID is in the anticollision chapter.
Getting the serial number of the card is surely the solution, but since this allows card tracking (I do not know, who this is, but she was present 10 minutes ago already) in privacy-aware context it is frequently only allowed after some kind of authentication (and possibly establishing a secure channel, so eavesdroppers don't benefit). For ideas, how to handle this, take a look at the ICAO specifications under BAC or EAC. I would not expect to find a privacy-aware solution for a card without being able to place specific information onto it.
I'm developing a NFC app that will have tags in public places, and in this way it would be necessary to lock the tags with a password or other tool, to avoid that someone deletes the information or modifies their content. The tags should be updatable at a later time. So, is possible to do this? Or when I lock a tag, does it stay read-only forever?
This very much depends on the type (and consequently price) of NFC tag that you use. Typical, cheap NFC tags (e.g. Type 1 tags like Topaz/Jewel or Type 2 tags like MIFARE Ultralight, NTAG203, Kovio 2K, or my-d NFC) do not allow this. They can only be permanently write-protected (and this is what you should typically do when installing tags in public places).
Other tags do provide some form authentication-based access control that can be used to restrict write-access tag memory, e.g.
MIFARE Ultralight C: mutual challenge response authentication using 3DES
NTAG21x, MIFARE Ultralight EV1, my-d move NFC: password based "authentication" with clear-text password. Be warned that a clear-text password may have sever security implications.
MIFARE DESFire (EV1): mutual challenge response authentication using DES, 3DES or AES
...
Authentication is not part of the NFC Forum's tag operation specifications and is consequently tag/tag manufacturer dependent. In order to use such advanced functionality on Android, you would need to implement the relevant commands youself (using the tech.transceive() method).
Note that Ndef.makeReadOnly() on Android does not necessarily set any hardware lock bits. This method may in some cases just as well only set a write protection on protocol level (i.e. set a flag that requests the NFC device not to write any data, but don't protect the actual data pages from being overwritten).
Yes of course but Android API don't have ready-made method to do it.
You have to use APDU to control access to tag.
The Ndef class has a makeReadOnly method: http://developer.android.com/reference/android/nfc/tech/Ndef.html#makeReadOnly() but you can't unlock tag.
I'm new in NFC thing, so I tested several phones with calling getTagId() method in HCE mode, and this is the result:
device | UID
LG G2 | random
LG G3 | static
S4 | random
HTC One Mini | static
Xiaomi mi3 | static
My questions:
Why do some phones have static UID and some do not? Is this chipset related?
Is it possible to get a fixed UID? I need it to authenticate the device.
On other side, I'm using Kitkat CyanogenMod 11 on Xperia M, but I did not manage to use it for HCE, why?
Any documents that can explain/support the answer?
Why do some phones have static UID and some do not? Is this chipset related?
That depends on the chipset and the implementation of the NFC stack. As far as I'm aware of, there are three different scenarios used by various Android NFC devices:
The device has a secure element and uses the static UID of that secure element.
The device generates a new random UID whenever it is turned on.
The device generates a new random UID on every activation by an external reader device. I.e. whenever an external HF field is applied to the NFC antenna of the Android device.
The device has no secure element but still uses a static UID (typically not unique), e.g. 0x01020304. [Thanks to ErikM for pointing this out.]
Is it possible to get a fixed UID?
Typically, you can't influence this. Specifically without modifying the Android device firmware (changes to the NFC stack) it's definitely not possible. See this answer for a method to set the UID value on Broadcom chipsets through modifying the libnfc-nci library.
I need it to authenticate the device.
Don't do this! See this answer for more information on that.
I want to route APDUs I get from an NFC Reader to the SIM Card. According to the HCE documentation I thought it would be possible simply by creating an OffHostApduService with the according routing-entries (which I did).
Sadly, the SIM does not seem to get any APDUs. SELECT-Commands that work when the SIM is directly attached to my workstation by a SIM-Reader return with 6a82 (File not found).
In LogCat I found two interesting bits of information:
Every time I shoot a select command which should be routed to the SIM, I get these entries:
01-14 10:44:18.501: D/BrcmNfcJni(1009): RoutingManager::stackCallback: event=0x17
01-14 10:44:18.501: D/BrcmNfcJni(1009): RoutingManager::stackCallback: NFA_CE_DATA_EVT; h=0x302; data len=12
01-14 10:44:18.501: D/HostEmulationManager(1009): notifyHostEmulationData
I think that this is a clue that the routing is not set correctly, since I think the Android OS should not be aware when the routing to the SIM is active, and a select or another command is sent to the SIM.
Every time I remove the phone from the NFC field of the reader, I receive the following error:
01-14 10:46:48.791: E/BrcmNfcNfa(1009): UICC[0x0] is not activated
I tried to track the cause of this error down and found the file external/libnfc-nci/src/nfa/ce/nfa_ce_act.chere which seems to belong to the Broadcom NFC Driver.
I think that the mistake is that the application cannot set the correct routing for the APDUs since the driver thinks that the SIM is not activated. In the moment I send the commands, the SIM is unlocked (PIN-Entry), but I doubt that this has anything to do with it since I don't have to unlock the SIM before using it in the card reader.
I use a Nexus 5 for testing. Does anybody have experience and / or a working example where the APDUs can be routed to the SIM instead of the CPU?
A quick check (analyzing the signals on the SWP pin of a UICC inserted into the device) revealed that the Nexus 5 is not activating the SIM as an NFC secure element (neither at boot nor when putting the phone on a smartcard reader).
However, I found two interesting files on the device's system partition:
/system/etc/libnfc-brcm-20791b05.conf and
/system/etc/libnfc-brcm.conf.
These two files seem to provide the configuration for the NFC controller (the first one a chip-sepecific configuration and the second one a chip-family specific one?).
After unlocking the bootloader, I was able to modify those files through adb by booting a clockworkmod recovery image, so I did some experimenting with the configuration parameters.
The result is that I managed to let the device activate the UICC (UICC was activated and registered its CE gates through SWP?), the device sometimes even notified the UICC about field status changes. However, with none of my modified configurations, I was able to get the reader to smoothly discover card emulation (this was working before, when only HCE was available on the device) nor to communicate with the UICC.
The interesting parameters in /system/etc/libnfc-brcm.conf seem to be:
NFA_MAX_EE_SUPPORTED: This is currently set to 0. I tried a value of 3, which seems to be the default.
ACTIVE_SE: This is currently set to 0 (no active SE). I tried to uncomment that line to let the device use the first SE detected.
NFA_HCI_STATIC_PIPE_ID_??: Should not be necessary but on out GS4 this is set to 0x71 for ?? = F3 and F4.
UICC_LISTEN_TECH_MASK: This is set to 0x00 on our GS4.
REGISTER_VIRTUAL_SE: I left this as it was (== commented out).
SCREEN_OFF_POWER_STATE: I did not experiment with this, but on our GS4 this is set to 3 (screen-off CE).
The interesting parameters in /system/etc/libnfc-brcm-20791b05.conf seem to be:
NFA_DM_START_UP_CFG: I've tried the commented-out parameters for UICC and I tried to use the configuration from our GS4. The value starts with a length byte and is structured in TLV format (one tag byte, one length byte, parameter data). The relevant tag for UICC activation seems to be C2, where the upper two bits in the second parameter byte disable the SWP interfaces of the NFC controller if set.
NFA_DM_PRE_DISCOVERY_CFG: The comments suggest that this need to be uncommented for UICC support.
It's been a while since I last played with card emulation on Android but AFAIK (I could be wrong), secure element access (internal or inside SIM) has not yet been opened to all developers (without some hacking). There are many non-technical issues regarding SE control which seem not yet solved (who keeps the biggest slice of the cake the Telcos or service providers?).
The news is that Google has taken a different approach with KitKat and its HCE, which basically consists on implementing a NFC card emulation mode without hardware secure element. IMHO this basically breaks the security required for the interesting card emulation mode applications: e-payment, ticketing, authentication, etc. Nexus 5 lacks such secure element and I doubt Google will pander to carriers by easing the access to secure element inside SIM, so I guess it still will not be possible to send APDUs to the SIM with stock firmware.
If you add the following to /etc/libnfc-brcm.conf
DEFAULT_ISODEP_ROUTE=0xF3
the UICC will receive APDUs
You also need all modifications above in libnfc-brcm.conf and libnfc-brcm-20791b05.conf
Up to Jelly Bean 4.3, normal way is to use nfc_extras and its method CardEmulationRoute (<route>, <nfcEe>) to route the UICC to the RF.
But on KITKAT, this brutal modification through DEFAULT_ISODEP_ROUTE is enough to have UICC Card Emulation enabled.
I want to fix uid for nexus s and when use the phone to tag at NFC shield. The shield will show id. But when it tag at the nfc shield, id is not same. Can I fix my uid ?
What you likely see is the NFCID: the NFC peer-to-peer ID. This ID is randomly generated anew by the NFC hardware on every NFC connection and cannot be fixed.
The current SDK does not allow you to use card emulation, so you can't use the phone as tag.
Because the ID changes for the peer-to-peer on every connection, you'll have to define an NDEF record with a text value in it. Make that value your fixed ID. On the other side, on the shield, you'll need to read out that record to find your fixed value/ID.
https://github.com/adafruit/Adafruit_NFCShield_I2C/tree/master/examples has some examples on how to manipulate NDEF records but only on MiFare classics. If you're using Ultralights or other kinds of tags, this will be different.