If I want my android phone to emulate a physical card to the following reader:
http://www.hidglobal.com/products/readers/iclass/rw100
Which AID would I have to use?
I was following this example:
https://developer.android.com/guide/topics/connectivity/nfc/hce.html#HceServices
But when debugging, my code never reaches the
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
method. Seems the Android device still represents itself as a unique number on a HW level so I was suspecting an incorrect AID within the code may be the cause?
FYI, I am using the Sony Xperia Z3 compact with an NXP NFC chip inside...
None.
Android HCE requires the reader to "speak" ISO/IEC 7816-4 over ISO/IEC 14443-4 (ISO-DEP). For ISO/IEC 14443 Type A this reader is only capable of reading the anti-collision identifier (UID) of cards but it does not send any APDUs. Consequently, the reader does not perform any AID based application selection.
Note that the UID cannot be configured through the Android HCE API and is randomly generated on many Android devices. Consequently, there is no sensible way you could use that reader in combination with Android devices that generate a random UID.
Related
I have a simple JavaCard applet installed on my SIM card. I try to communicate with my applet using Omnikey 5121 CL reader and NFC-enabled Sony Xperia L through NFC/SWP (single wire protocol).
The problem is I cannot select the applet - as a status word I get 6999. The LED light is turned on, so I suppose there is some communication between reader and the SIM card. Moreover, I cannot select my security domain either.
However, when I put the SIM card into a standard contact smartcard reader, everything works fine.
Is there any extra configuration of Android OS, SIM card, NFC modem etc. I have to setup before communicating with SIM card over NFC? Any ideas?
More information:
ATR of SIM accessed in the contact way:
3B9F96C00A3FC6A08031E073FE211F65D001900F3B810FE6
ATR (generated by PCSC from ATS) of SIM accessed over NFC in the contactless way:
3B8880010000000000817000F8
My INSTALL for INSTALL APDU: (worked, finally!)
80E6040C32 //CLA INS P1 P2 Lc
0CF0AAAAAAAAAAAAAAAABBBBBB // AIDs
09F0AAAAAAAAAAAAAAAA
09F0AAAAAAAAAAAAAAAA
01
00 //privileges
0B //length of parameters
EF07 //system parameters
A005A5038201FF
C900 //applet parameters
00
Receiving status code 6999 in response to the SELECT (by AID) command is a clear indication that the applet was not found/not selectable. If the applet has been installed and is selectable (using the same AID) over the contact interface of the UICC/SIM card, then it is likely not made selectable over the SWP (contactless) interface. Typically secure elements allow to selectively enable/disable applets for specific interfaces (in addition to this, applets can detect over which interface they are selected and can react accordingly).
Applets typically need to be explicitly made selectable over the contactless interface by setting the Contactless Protocol Parameters in the INSTALL (for MAKE SELECTABLE) command (or later on by doing a registry update). See Amendment C to the Global Platform Card specification for further details.
Btw. the security domain not being selectable over the contactless interface is not unusual for a SIM card. Card management is typically restricted to the contact interface for security reasons. (Card management over the contactless interface is typically not used in production environments anyways.)
I have an LG D320n Android phone, elechouse's PN532 nfc module and Stollmann's NFCPlayer with which I can read NFC tags properly.
I tested a sample from here: https://github.com/grundid/host-card-emulation-sample
It works fine, when I read one Android device as tag with another Android device as reader. But I can not read the Android device as tag with PN532 reader through NFCPlayer. I want reader to read an NDEF message from the Android device acting as a tag, but NFCPlayer doesn't even recognise the Android device. I think I have to write some modifications on the Android side but I can't figure it out what to do. I think I don't have enough knowlege about how NFC communication and HCE work, even though I read this:
https://developer.android.com/guide/topics/connectivity/nfc/hce.html
I would really appreciate any guideline that could help me understand what am I missing here.
The grundid example app should be discovered by NFCPlayer as a "legacy tag" (tab "R/W: Legacy") as it does not implement the NDEF abstraction layer. On that tab, you can exchange PDUs (APDUs in the case of HCE) with the emulated smartcard. A valid APDU for the example app would be
00 A4 04 00 07 F0010203040506 00
You can send this APDU by typing it into the PDU field and clicking on the "Exch. PDU" button. Note that the grundid HCE app does not even implement ISO/IEC 7816-4 response APDUs. Hence, you may run into troubles with some contactless smartcard readers.
If you want your emulated smartcard to be discoverabe by NFCPlayer as NFC Forum Type 4 tag containing an NDEF message (tab "R/W: NDEF"), you would need to implement the NFC Forum Type 4 Tag Operation specification (as defined by the NFC Forum. This specification defines how data must be stored on an (emulated) ISO/IEC 14443-4 smartcard to be interpreted as NDEF tag. As a starting point you could use this NDEF on HCE example app (though, the quality and reliability of that code is questionable). This example implements the smartcard filesystem for storing NDEF data.
When I put SIII (Android 4.3) on ACR122U NFC reader the LED keeps blinking green. When I put Samsung S4 (Android 4.3) LED turns green till the time phone is on the reader. In both the cases NFC is turned on and device is in unlocked state.
This behaviour translates into frequent disconnections in SIII and a stable connection on S4. Why two phones behave differently? I am aware of the fact that two phones have NFC chipsets from two different vendors namely NXP and Broadcom.
My question is what is the source for such inconsistent behaviour among these devices?
Another question is why does phone give an ATR at all?
The command sequence for software card emulation using an ACR122U/PN532 can be found in this answer.
In addition to that, there are different versions of the ACR122U:
Some always indicate the presence of a smartcard. In that case it is possible to connect to the "simulated" card using
// SCardConnect with SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY
Card card = cardTerminal.connect("*");
CardChannel cardChannel = card.getBasicChannel();
After that, PN532 commands can be sent using APDU wrapping:
> FF000000 Lc PN532-COMMAND
< PN532-RESPONSE 9000
with the cardChannel.transmit method:
CommandAPDU commandAPDU = ...
// SCardTransmit
Response responseAPDU = cardChannel.transmit(commandAPDU);
Other versions of the ACR122U do not always "simulate" the presence of a smartcard. Instead they automatically poll for contactless cards and only indicate card-presence if an actual card is presented to the reader. In that case using cardTerminal.connect("*"); would be only possible if there is an actual card present. However, this is typically not the case in situations where the ACR122U is used in software card emulation mode. In that case it is still possible to establish a connection to the reader using direct mode
// SCardConnect with SCARD_SHARE_DIRECT
Card card = cardTerminal.connect("direct");
After that, the same APDU-wrapped PN532 commands can be exchanged with the reader using escape commands (you might want to check the manual if the escape command is correct for your reader version):
final int IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND = 0x003136B0; //IOCTL(3500) for Windows
//final int IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND = 0x42000DAC; //IOCTL(3500) for Linux
byte[] commandAPDU = ...
// SCardControl
byte[] responseAPDU = card.transmitControlCommand(IOCTL_SMARTCARD_ACR122_ESCAPE_COMMAND, commandAPDU);
Using a Nexus 4 and the latest Android API level 18 to communicate with a Mifare DESFire EV1 AES tag is giving me a headache. Following the NXP native protocol in order to write and read this type of tag, these steps must be followed:
Select application
Authenticate
Write or Read
To do it so, I use Android's IsoDep class which provides access to ISO 14443-4 properties and I/O operations. The very weird thing about it is that once I send the select application native command I get an unexpected response. Imagine I have the AID F4013D so I send:
-> 5AF4013D
<- 6E00
All possible responses must be one byte length (success 0x00 or error_code) and never two or more. Thus, the 0x6E before the success response is absolutely unexpected. It does not happen always, and when it does not and works fine, the select application and authentication processes work fine. However once authenticated the write command does not have a correct behavior, all write commands finishes with a 0xAF from the PICC instead of a success 0x00. It seems like the PICC expect some extra data when it should not (I send the correct length payload). If I send any other command I get a 0xCA (Command Aborted) error code.
-> 5AF4013D
<- 00 /*Success*/
-> AA01
<- AFA8394ED57A5E83106B4EE72FD2BB0CC4
-> AF148F525E1DDE0AD6AB60B4B615552475C91F2E8D89B8523E4465113DD5BD19C6
<- 0066D255C93F2F492AFE3715C88964F1BD /*Authentication success*/
-> 3D02000000030000222222 /*Write 3 bytes to file nÂș2*/
<- AF /*Unexpected, 0x00 was expected*/
As it is normal, if I send these type of commands with a personal reader (non Android NFC) it always works fine. It seems that something in the Android NFC API is going strange, when it should just be a raw data transporter which never interprets or modifies data.
I have also tried with ISO 7816-4 APDU structure with the same result. As a curiosity, with a Galaxy Nexus does not happen the select application strange response, but yes the write command one always.
(1) For the first part concerning the status code 6E00:
6E 00 is not a "strange byte 0x6E + success status code 0x00". Instead it is a response APDU status word 6E 00 ("Class not supported"). This indicates that there was previous communication with the card using APDU-based access (e.g. Android itself tried to read the card as Type 4 tag and did not reset the connection afterwards). Thus, the card will expect all further communication to be in ISO 7816-4 APDUs. In that case (i.e. if you receive an ISO 7816-4 status code like 6E 00), you could continue using DESFire APDU wrapped commands by simply wrapping your native commands.
EDIT: In fact, this is somewhat expected behavior on an NFC device. The idea is that an NFC device will automatically scan detected tags for NDEF messages. In the case of a DESFire card, the NFC device will detect the card as potential Type 4 tag. Thus the NFC device will send ISO 7816-4 APDUs as it would send to any other Type 4 tag. Hence, if the NFC device doesn't reset the communication with the tag before handing the detected tag to the app, the app can only communicate using ISO 7816-4 APDUs. Note, however, that I would consider it a bug that this happens only for some activations on the same device. In my opinion, the behavior on one specific device model should be consistent.
EDIT: While I would not consider this behavior a bug, it is actually caused by a known bug (#58773) in Android's NFC stack for devices with Broadcom NFC controller. On affected devices, the automatic presence check sends ISO 7816-4 APDUs at timed intervals that cause DESFire cards to switch into ISO 7816-4 APDU mode.
(2) For the second part concerning the (unexpected) response code 0xAF:
Could it be that your file's communication settings are setup for either "plain communication secured by MACing" or "fully enciphered communication"? In that case, simply sending the three data bytes would not be enough. Instead you would need to send either the plain data plus MAC or the padded, CRCed and encyrypted data. Hence the 0xAF indicating that the card expects further data.
EDIT: So to summarize the comments below. After sending further bytes (one byte at a time for each received 0xAF status code: AF FF) it turned out that exactly 8 more bytes were expected by the card. 8 bytes is exactly the size of the CMAC for AES authentication. Thus, the communication settings were set to "plain communication secured by MACing".
I am working on an application for Android reading a contactless smart card but I have some problems with my Galaxy S3.
Before to describe problems, I need to precise that on a PC, I can communicate perfectly with the card using the smartcardio API in Java and NFC readers from different manufacturers.
This card is detected as supporting technologies "IsoDep" and "NfcB" by the NFC stack.
However, when I send my apdu command with "transceive", I get an exception "Transceive failed". I have tried to increase timeout but no better result.
iso = IsoDep.get(tag);
if (iso!=null) {
try {
iso.connect();
// txMessage is a TextView object used for debugging purpose
txMessage.setText("Max:"+iso.getMaxTransceiveLength()+" timeout:"+iso.getTimeout()+" connected:"+iso.isConnected());
iso.setTimeout(2000);
txMessage.setText("Max:"+iso.getMaxTransceiveLength()+" timeout:"+iso.getTimeout()+" connected:"+iso.isConnected());
byte[] command = new byte[] {(byte) 0x00, (byte) 0xA4, (byte) 0x04,(byte) 0x00, (byte) 0x06,(byte) 0xA0,(byte) 0x00,(byte) 0x00, (byte) 0x00,(byte) 0x12,(byte) 0x00};
byte[] response = iso.transceive(command);
} catch (IOException e) {
txMessage.setText(txMessage.getText()+"\n"+e.getMessage());
}
}
When running this code, I get:
Max:261 timeout:309 connected: true
Max:261 timeout:2474 connected: true
Transceive failed
I have noticed that this card requires to be very close of the NFC antenna to work. I need to remove the additional plastic protection case (not the back cover) of my phone in order the card would be detected (I guess powered).
Before to post, I have read NFC typeb card not getting detected by any NFC application (like:nfctaginfo) and Android isodep.isConnected() returns false and maximum Transceive length:0 byte ,for type B card.? and several other posts elsewhere (http://forum.xda-developers.com/showthread.php?t=1705970 , http://code.google.com/p/android/issues/detail?id=35960 ) but I did not find a solution.
A possible solution would be to try to communicate with an external antenna but I am not sure where to connect it? On battery connector where there is no "+" and "-"?
Another solution would be to try to communicate with the card with NfcB (NfcB nfcb = NfcB.get(tag);), but I do not know the ISO14443-3B protocol (I only know quite well APDU, T0-TPDU but not other TPDU protocols).
Just to be sure, I have updated my phone to Android 4.1.2 (instead of 4.1.1) but no better result.
I have a Samsung Galaxy S3 too and I noticed that the connection performance for TypeB contactless cards is worse than for TypeA. Raising the timeout value seems to be a quick fix for problems of this kind, but as it didn't work for you, the problem might be with the strength of the RF-field. Have you tested if the call of transceive() fails because of the timeout or because of a connection loss? Maybe you could try raising the timeout even further, some operations might take a long time on a smart card.
Another suggestion to your problem is to remove the backcover of your S3 and place the smart card directly on the battery (the NFC antenna is integrated in there). In my experience it makes a slight difference where the chip is located on the smart card, so you could experiment with the orientation of the card. You might test this by sliding the card onto the battery from the bottom of the device to the top.
In my work with the Galaxy S3 (Android 4.1.1) I was able to connect to and transceive data to TypeA and TypeB contactless smart cards (German eID cards). I noticed that the TypeB card was lost sometimes without any reason while being idle. But I can send and receive data with it anyway. Even when the Chip on the card has to perform some computation and hence needs slightly more power from the RF field, the field of the NFC antenna seems sufficiently strong to keep the connection in my case. Maybe your card is not properly designed to work with lower power RF fields? Unfortunately to my knowledge there is no possibility to raise the power output of the NFC antenna on Android devices.
Communicating via the NfcB (NfcB nfcb = NfcB.get(tag);) does not seem to make any difference to me. I am able to comunicate via the IsoDep Object and transceive data perfectly.
Using an external or additional antenna would be worth a try. In this YouTube video it is shown how one can put an additional NFC antenna into the Galaxy S4. In the video you will notice the external antenna pins on the back of the S4. When watching the third picture here (Galaxy SIII teardown) - the one with the battery taken out - you will notice that there are additional antenna pins on the back of the SIII as well. The two golden contact pins on the left side. Googling a bit showed that these pins are named 'ANT500' and 'ANT501', so they are probably external NFC antenna contacts. If you search for "Samsung Galaxy Note2 external NFC antenna" or something similar on eBay (or any search engine), you will get the antenna used in the YouTube video. There are no official external NFC antennas for the SIII nor for the S4, but probably it will work. The antenna is not very expensive (currently around $5), so you might give it a try.
It is definitely a timeout thing, and a compatibility thing with NXP NFC chips (like the one in the S3)
I have worked with Type B tags on an antenna with a higher Q factor than that of a typical mobile phone antenna, and when doing ISO-DEP I need to still change the default timeouts of the NFC chip that I'm using (NXP PN532). Type A modulation was developed by Phillps, now NXP. Type B modulation was developed by Motorolla, and is under license to NXP for its reader chips, so only a basic implementation is included relative the the Type A implementation.
I am not doing this on an Android, but an embedded platform, so I have full access to the NFC chip's features. Thus, only by using a more basic transeiving method that requires the application to handle the 14443-4 protocol and extending the timeout tolerance of the reader was I able to talk to a Type B tag using ISO-DEP
Android 4.4 has something called reader mode, that may have a feature that enables you to extend this timeout.