Emulating a PKI smart card with CyanogenMod 9.1

We discussed the embedded secure element available in recent Android devices, it's execution environment and how Google Wallet makes use if it in the last series of articles. We also saw that unless you have a contract with Google and have them (or the TSM they use) distribute your applets to supported devices, there is currently no way to install anything on the embedded secure element. We briefly mentioned that CyanogenMod 9.1 supports software card emulation and it is a more practical way to create your own NFC-enabled applications. We'll now see how software card emulation works and show how you can use it to create a simple PKI 'applet' that can be accessed via NFC from any machine with a contactless card reader.

Software card emulation

We already know that if the embedded secure element is put in virtual mode it is visible to external readers as a contactless smartcard. Software card emulation (sometimes referred to as Host Card Emulation or HCE) does something very similar, but instead of routing commands received by the NFC controller to the SE, it delivers them to the application processor, and they can be processed by regular applications. Responses are then sent via NFC to the reader, and thus your app takes the role of a virtual contactless 'smartcard' (refer to this paper for a more thorough discussion).  Software card emulation is currently available on BlackBerry phones, which offer standard APIs for apps to register with the OS and process card commands received over NFC. Besides a BlackBerry device, you can use some contactless  readers in emulation mode to emulate NFC tags or a full-featured smart card. Stock Android doesn't (yet) support software card emulation, even though the NFC controllers in most current phones have this capability. Fortunately, recent version of CyanogenMod integrate a set of patches that unlock this functionality of the PN544 NFC controller found in recent Nexus (and other) devices. Let's see how it works in a bit more detail.

CyanogenMod implementation

Android doesn't provide a direct interface to its NFC subsystem to user-level apps. Instead, it leverages the OS's intent and intent filter infrastructure to let apps register for a particular NFC event (ACTION_NDEF_DISCOVERED, ACTION_TAG_DISCOVERED and ACTION_TECH_DISCOVERED) and specify additional filters based on tag type or features. When a matching NFC tag is found, interested applications are notified and one of them is selected to handle the event, either by the user or automatically if it is in the foreground and has registered for foreground dispatch. The app can then access a generic Tag object representing the target NFC device and use it to retrieve a concrete tag technology interface such as MifareClassic or IsoDep that lets it communicate with the device and use its native features. Card emulation support in CyanogenMod doesn't attempt to change or amend Android's NFC architecture, but integrates with it by adding support for two new tag technologies: IsoPcdA and IsoPcdB. 'ISO' here is the International Organization for Standardization, which among other things, is responsible for defining NFC communication standards. 'PCD' stands for Proximity Coupling Device, which is simply ISO-speak for a contactless reader. The two classes cover the two main NFC flavours in use today (outside of Japan, at least) -- Type A (based on NXP technology) and Type B (based on Motorolla technology). As you might have guessed by now, the patch reverses the usual roles in the Android NFC API: the external contactless reader is presented as a 'tag', and 'commands' you send from the phone are actually replies to the reader-initiated communication. If you have Google Wallet installed the embedded secure element is activated as well, so touching the phone to a reader would produce a potential conflict: should it route commands to the embedded SE or to applications than can handle IsoPcdA/B tags? The CyanogenMod patch handles this by using Android's native foreground dispatch mechanism: software card emulation is only enabled for apps that register for foreground dispatch of the relevant tag technologies. So unless you have an emulation app in the foreground, all communication would be routed to Google Wallet (i.e., the embedded SE). In practice though, starting up Google Wallet on ROMs with the current version of the patch might block software card emulation, so it works best if Google Wallet is not installed. A fix is available, but not yet merged in CyanogenMod master (Updated: now merged, should roll out with CM10 nightlies) .

Both of the newly introduced tag technologies extend BasicTagTechnology and offer methods to open, check and close the connection to the reader. They add a public transceive() method that acts as the main communication interface: it receives reader commands and sends the responses generated by your app to the PCD. Here's a summary of the interface:

abstract class BasicTagTechnology implements TagTechnology {
    public boolean isConnected() {...}
           
    public void connect() throws IOException {...}
   
    public void reconnect() throws IOException {...}
     
    public void close() throws IOException {...}

    byte[] transceive(byte[] data, boolean raw) throws IOException {...}
}

Now that we know (basically) how it works, let's try to use software card emulation in practice.

Emulating a contactless card

As discussed in the previous section, to be able to respond to reader commands we need to register our app for one of the PCD tag technologies and enable foreground dispatch. This is no different than handling stock-supported  NFC technologies. We need to add an intent filter and a reference to a technology filter file to the app's manifest:

<activity android:label="@string/app_name" 
                  android:launchmode="singleTop"
                  android:name=".MainActivity"
  <intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED" />
  </intent-filter>

  <meta-data android:name="android.nfc.action.TECH_DISCOVERED" 
                android:resource="@xml/filter_nfc" />
</activity>

We register the IsoPcdA tag technology in filter_nfc.xml:

<resources>
  <tech-list>
    <tech>android.nfc.tech.IsoPcdA</tech>
  </tech-list>
</resources>

And then use the same technology list to register for foreground dispatch in our activity:

public class MainActivity extends Activity {

  public void onCreate(Bundle savedInstanceState) {
    pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    filters = new IntentFilter[] { new IntentFilter(
                NfcAdapter.ACTION_TECH_DISCOVERED) };
    techLists = new String[][] { { "android.nfc.tech.IsoPcdA" } };
  }
  
  public void onResume() {
    super.onResume();
    if (adapter != null) {
      adapter.enableForegroundDispatch(this, pendingIntent, filters,
                    techLists);
    }
  }

  public void onPause() {
    super.onPause();
    if (adapter != null) {
      adapter.disableForegroundDispatch(this);
    }
  }

}

With this in place, each time the phone is touched to an active reader, we will get notified via the activity's onNewIntent() method. We can get a reference to the Tag object using the intent's extras as usual. However, since neither IsoPcdA nor its superclass are part of the public SDK, we need to either build the app as part of CyanogenMod's source, or, as usual, resort to reflection. We choose to create a simple wrapper class that calls IsoPcdA methods via reflection, after getting an instance using the static get() method like this:

Class cls = Class.forName("android.nfc.tech.IsoPcdA");
Method get = cls.getMethod("get", Tag.class);
// this returns an IsoPcdA instance
tagTech = get.invoke(null, tag);

Now after we connect() we can use the transceive() method to reply to reader commands. Note that since the API is not event-driven, you won't get notified with the reader command automatically. You need to send a dummy payload to retrieve the first reader command APDU. This can be a bit awkward at first, but you just have to keep in mind that each time you call transceive() the next reader command comes in via the return value. Unfortunately this means that after you send your last response, the thread will block on I/O waiting for transceive() to return, which only happens after the reader sends its next command, which might be never. The thread will only stop if an exception is thrown, such as when communication is lost after separating the phone from the reader. Needless to say, this makes writing robust code a bit tricky. Here's how to start off the communication:

// send dummy data to get first command APDU
// at least two bytes to keep smartcardio happy
byte[] cmd = transceive(new byte[] { (byte) 0x90, 0x00 });

Writing a virtual PKI applet

Software card emulation in CyanogneMod is limited to ISO 14443-4 (used mostly for APDU-based communication), which means that you cannot emulate cards that operate on a lower-level protocol such as MIFARE Classic. This leaves out opening door locks that rely on the card UID with your phone (the UID of the emulated card is random) or getting a free ride on the subway (you cannot clone a traffic card with software alone), but allows for emulating payment (EMV) cards which use an APDU-based protocol. In fact, the first commercial application (company started by patch author Doug Yeagerthat makes use of Android software card emulation, Tapp, emulates a contactless Visa card and does all necessary processing 'in the cloud', i.e., on a remote server. Payment applications are the ones most likely to be developed using software card emulation because of the potentially higher revenue: at least one other company has announced that it is building a cloud-based NFC secure element. We, however, will look at a different use case: PKI.

PKI has been getting a lot of bad rep due to major CAs getting compromised every other month, and it has been stated multiple times that it doesn't really work on the Internet. It is however still a valid means of authentication in a corporate environment where personal certificates are used for anything from desktop login to remote VPN access. Certificates and associated private keys are often distributed on smart cards, sometimes contactless or dual-interface. Since Android now has standard credential storage which can be protected by hardware on supported devices, we could use an Android phone with software card emulation in place of a PKI card. Let's try to write a simple PKI 'applet' and an associated host-side client application to see if this is indeed feasible.

A PKI JavaCard applet can offers various features, but the essential ones are:
  • generating or importing keys
  • importing a public key certificate
  • user authentication (PIN verification)
  • signing and/or encryption with card keys
Since we will be using Android's credential storage to save keys and certificates, we already have the first two features covered. All we need to implement is PIN verification and signing (which is actually sufficient for most applications, including desktop login and SSL client authentication). If we were building a real solution, we would implement a well known applet protocol, such as one of a major vendor or an open one, such as the MUSCLE card protocol, so that we can take advantage of desktop tools and cryptographic libraries (Windows CSPs and PKCS#11 modules, such as OpenSC). But since this is a proof-of-concept exercise, we can get away by defining our own mini-protocol and only implement the bare minimum. We define the applet AID (quite arbitrary, and may be in already in use by someone else, but there is really no way to check) and two commands: VERIFY PIN and SIGN DATA. The protocol is summarized in the table below:

Virtual PKI applet protocol
CommandCLAINSP1P2LcDataResponse
SELECT00A4040006AID: A00000000101109000/6985/6A82/6F00
VERIFY PIN8001XXXXPIN length (bytes)PIN characters (ASCII)9000/6982/6985/6F00
SIGN DATA8002XXXXSigned data length (bytes)Signed data9000+signature bytes/6982/6985/6F00

The applet behaviour is rather simple: it returns a generic error if you try to send any commands before selecting it, and then requires you to authenticate by verifying the PIN before signing data. To implement the applet, we first handle new connections from a reader in the main activity's onNewIntent() method, where we receive an Intent containing a reference to the IsoPcdA object we use to communicate with the PCD. We verify that the request comes from a card reader, create a wrapper for the Tag object, connect() to the reader and finally pass control to the PkiApplet by calling it's start() method.

Tag tag = (Tag) intent.getExtras().get(NfcAdapter.EXTRA_TAG);
List techList = Arrays.asList(tag.getTechList());
if (!techList.contains("android.nfc.tech.IsoPcdA")) {
  return;
}

TagWrapper tw = new TagWrapper(tag, "android.nfc.tech.IsoPcdA");
if (!tw.isConnected()) {
  tw.connect();
}

pkiApplet.start(tw);

The applet in turn starts a background thread that reads commands until available and exits if communication with the reader is lost. The implementation is not terribly robust, but is works well enough for our POC:

Runnable r = new Runnable() {
    public void run() {
        try {
            // send dummy data to get first command APDU
            byte[] cmd = transceive(new byte[] { (byte) 0x90, 0x00 });
            do {
                // process commands
            } while (cmd != null && !Thread.interrupted());
        } catch (IOException e) {
            // connection with reader lost
            return;
        }
    }
};

appletThread = new Thread(r);
appletThread.start();


Before the applet can be used it needs to be 'personalized'. In our case this means importing the private key the applet will use for signing and setting a PIN. To initialize the private key we import a PKCS#12 file using the KeyChain API and store the private key alias in shared preferences. The PIN is protected using 5000 iterations of PBKDF2 with a 64-bit salt. We store the resulting PIN hash and the salt in shared preferences as well and repeat the calculation against the PIN we receive from applet clients to check if it matches. This avoids storing the PIN in clear text, but keep in mind that a short numeric-only PIN can be brute-forced in minutes (the app doesn't restrict PIN size, it can be up to 255 characters (bytes), the maximum size of APDU data). Here's how our 'personalization' UI looks like:


To make things simple, applet clients send the PIN in clear text, so it could theoretically be sniffed if NFC traffic is intercepted. This can be avoided by using some sort of a challenge-response mechanism, similar to what 'real' (e.g., EMV) cards do. Once the PIN is verified, clients can send the data to be signed and receive the signature bytes in the response. Since the size of APDU data is limited to 255 bytes (due to the single byte length field) and the applet doesn't support any sort of chaining, we are limited to using RSA keys up to 1024 bits long (a 2048-bit key needs 256 bytes). The actual applet implementation is quite straightforward: it does some minimal checks on received APDU commands, gets the PIN or signed data and uses it to execute the corresponding operation. It then selects a status code based on operation success or failure and returns it along with the result data in the response APDU. See the source code for details.

Writing a host-side applet client

Now that we have an applet, we need a host-side client to actually make use of it. As we mentioned above, for a real-world implementation this would be a standard PKCS#11 or CSP module for the host operating system that plugs into PKI-enabled applications such as browsers or email and VPN clients. We'll however create our own test Java client using the Smart Card I/O API (JSR 268). This API comes with Sun/Oracle Java SDKs since version 1.6 (Java 6), but is not officially a part of the SDK, because it is apparently not 'of sufficiently wide interest' according to the JSR expert group (committee BS at its best!). Eclipse goes as far as to flag it as a 'forbidden reference API', so you'll need to change error handling preferences to compile in Eclipse. In practice though, JSR 268 is a standard API that works fine on Windows, Solaris, Linux an Mac OS X (you may have to set the sun.security.smartcardio.library system property to point to your system's PC/SC library), so we'll use it for our POC application. The API comes with classes representing card readers, the communication channel and command and response APDUs. After we get a reference to a reader and then a card, we can create a channel and exchange APDUs with the card. Our PKI applet client is a basic command line program that waits for card availability and then simply sends the SELECT, VERIFY PIN and SIGN DATA commands in sequence, bailing out on any error (card response with status different from 0x9000). The PIN is specified in the first command line parameter and if you pass a certificate file path as the second one, it will use it to verify the signature it gets from the applet. See full code for details, but here's how to connect to a card and send a command:

TerminalFactory factory = TerminalFactory.getDefault();
CardTerminals terminals = factory.terminals();

Card card = waitForCard(terminals);
CardChannel channel = card.getBasicChannel();
CommandAPDU cmd = new CommandAPDU(CMD);
ResponseAPDU response = channel.transmit(cmd);

Card waitForCard(CardTerminals terminals)
            throws CardException {
    while (true) {
        for (CardTerminal ct : terminals
                    .list(CardTerminals.State.CARD_INSERTION)) {
            return ct.connect("*");
        }
        terminals.waitForChange();
    }
}

And to prove that this all works, here's the output from a test run of the client application:

$ ./run.sh 1234 mycert.crt 
Place phone/card on reader to start
--> 00A4040006A0000000010101
<-- 9000
--> 800100000431323334
<-- 9000
--> 80020000087369676E206D6521
<-- 11C44A5448... 9000 (128)

Got signature from card: 11C44A5448...
Will use certificate from 'mycert.crt' to verify signature
 Issuer: CN=test-CA, ST=Tokyo, C=JP
 Subject: CN=test, ST=Tokyo, C=JP
 Not Before: Wed Nov 30 00:04:31 JST 2011
 Not After: Thu Nov 29 00:04:31 JST 2012

Signature is valid: true

This software implementation comes, of course, with the disadvantage that while the actual private key might be protected by Android's system key store, PIN verification and other operations not directly protected by the OS will be executed in a regular app. An Android app, unlike a dedicated smart card, could be compromised by other (malicious) apps with sufficient privileges. However, since recent Android devices do have (some) support for a Trusted Execution Environment (TEE), the sensitive parts of our virtual applet can be implemented as Trusted Application (TA) running within the TEE. The user-level app would then communicate with the TA using the controlled TEE interface, and the security level of the system could come very close to running an actual applet in a dedicated SE.

Summary

Android already supports NFC card emulation using an embedded SE (stock Android) or the UICC (various vendor firmwares). However, both of those are tightly controlled by their owning entities (Google or MNOs), and there is currently no way for third party developers to install applets and create card emulation apps. An alternative to SE-based card emulation is software card emulation, where an user-level app processes reader commands and returns responses via the NFC controller. This is supported by commonly deployed NFC controller chips, but is not implemented in the stock Andorid NFC subsystem. Recent versions of CyanogneMod however do enable it by adding support for two more tag technologies (IsoPcdA and IsoPcdB) that represent contactless readers instead of actual tags. This allows Android applications to emulate pretty much any ISO 14443-4 compliant contactless card application: from EMV payment applications to any custom JavaCard applet. We presented a sample app that emulates a PKI card, allowing you to store PKI credentials on your phone and potentially use it for desktop login or VPN access on any machine equipped with a contacltess reader. Hopefully software card emulation will become a part of stock Android in the future, making this and other card emulation NFC applications mainstream.

Comments

Anargyros said…
Hi Nikolay,

I would like to thank you about your current documentation. Now, we have the ability to enable software card emulation as well as to implement our payment applications on Android phones. On the current documentation, the host-side applet client is a Java client using the Smart Card I/O API (PC). Is it possible the host-side applet client to be an Android NFC Reader app (Android phone) and it will communicate with your software card emulation?

br,
Anargyros
Nikolay Elenkov said…
Technically, yes. In practice however, if you touch another NFC enabled device (one with card emulation on, software or using the SE), Android will try to activate P2P mode on the client device automatically and won't pick up the card emulation one as a Tag. There doesn't seem to be a way to disable this behaviour via the UI or the SDK API, so you might have to modify Android to get rid of it.
Anargyros said…
Thanks for response, Nikolay. I have downloaded the android source code in order to disable the P2P mode. In libnfc-nxp, I disabled #define ENABLE_P2P (put it in comments), but when I started the device, the NFC was disabled. Do you know which value is responsible for the activation of P2P mode? Thanks in advance.
Nikolay Elenkov said…
I don't know the details, but most likely you need to change something in the upper layers too. Look at the Nfc.apk source int packages/apps/Nfc an search for relevant code. Also check logcat output for related error messages.
pawan said…
Thanks for the amazing write up. Really helped met get started with CM10 and Software Card Emulation. I was browsing through the source code on github and from what I observe. The android application is sending a "good response" 90 00 APDU to get the initial command from the reader. You mentioned here that it is to make smartcardio happy. This is okay in a controlled environment where we also control the reader side communication ( like this demo ) but what if we need to capture the command sent and respond accordingly for example in communication with a POS terminal ?
Nikolay Elenkov said…
The actual contents should be ignored by the NFC subsystem, so it shouldn't matter. What the comment means is that smartcardio will complain if you send less that two bytes. In any case, you should test with an actual POS terminal to see how it behaves.
amin abbasi said…
thanks for this documentation , i want to use se-pki-client,i dont know how to use in windows and how to run eclips
Hi Nikolay,
in the blog post you wrote:

"Software card emulation in CyanogneMod is limited to ISO 14443-4 (used mostly for APDU-based communication), which means that you cannot emulate cards that operate on a lower-level protocol such as MIFARE Classic. This leaves out opening door locks that rely on the card UID with your phone (the UID of the emulated card is random)"

In the past I've tested certain implementations (for a research project) that use Mifare Classic 1K and 4K cards. My tests with copied cards have shown that the implemented systems do not use the Sector 0 of the Mifare Classic card. Would that mean that with the current Cyanogen NFC emulation mode it could be possible to emulate a Mifare Classic Card successfully ? Given that the backend system of a lock does not care about Sector 0 of the card?

Nikolay Elenkov said…
Basically Mifare works on a lower-level protocol that CM cannot emulate. It's not about a particular sector -- even if the system uses something other than the UID (a value in a dedicated block(s)), etc. you cannot emulate the Mifare file system, so you are out of luck. If the lock uses anything ISO 14443-4 you might be able to use it with a CM phone.
Nikolay Elenkov said…
Using in Windows should actually be easier, because PCSC is guaranteed to work (as long as you have the driver for you reader, of course). You don't have to compile with Eclipse, a simple batch file or Ant will do.
Nikolay,
Thank you very much for the fast reply and for clearing up my confusion. I read up a bit on the ISO standard from my understanding (as far as the standardization goes) Mifare Classic uses the standards ISO 14443-1,2,3 and instead of using ISO 14443-4 they use their own proprietary protocol. So please correct me if I am wrong, it's not a lower level ( technically ) but rather a different implementation? I am basing this on the fact that Mifare Classic is ISO 14443-3 compliant ( so it has to build on top of that standard ).

I also wanted to clear one more thing up if you have the time. Where does ISO 14443-A (like Mifare Classic) and ISO 14443-B come into play here? The information that I could find is a bit messy and there seems to be a bit too much confusion around it. If you could point me to a decent source or a Ven diagram :D .

Regards,
Sebastian Carlier.
Nikolay Elenkov said…
You are actually somewhat wrong. 14443-3 is the lower level protocol and deals with discovering cards and establishing a connection. 14443-4 is implemented on top of that and lets you transmit actual data packets. Mifare sits somewhere between -3 and -4, so it is indeed a lower level protocol compared to -4. As you have found, -3 comes in different flavours and was actually standardized after cards were already widely used, so it was fitted to match what was already in use (Type A cards, etc. by NXP and Type B by Motorola).

You might want to read the ISO standards to clear any confusion. You need to pay for the final versions, but you can find the final drafts on the Internet for free. For example here: http://wg8.de/sd1.html#14443
Nikolay,
Thanks again for the fast reply, you saved me a lot of time. I will look into the details of those documents knowing more or less what to expect.
Hi Nikolay,
Thanks a lot for the superb tutorial and all the provided information+code.

Using the ideas in your post, I could export a javacard applet that we used for a access system embedded in an UICC to a android-app running on a CM10 "Nexus S" and "Galaxy Nexus". Having done this, we could not only test the app running on the mobile device, successfully but it was also way faster than card emulation on the UICC variant.

I have in this point 2 questions:
1) The instability problem. You also mention this problem in your post. I observed that after the last APDU exchange with the reader and mobile device, the transceive() of the BasicTechTechnology method throws an "transceive failed" exception which I cannot analyze further from the SDK. Is it a behavior that you also encountered? If yes, would you have hint or idea to fix or make the transaction flow more robust?
In the current situation, only after removing and retouching the handset the transaction flow can be repeated successfully again.

2) This question is more essential tough I'm not sure you can comment on that: Having HCE enabled in the CM, developers can start to focusing on real-world applications such as payment and access - like SimplyTapp just doing it. In order to make these solutions widespread tough, HCE must be available in the android's official releases as you can't say common mobile users to root and flash their handsets with CM before they can start using your app. How do you see the chances that Google would sooner or later accept and release the HCE functionality?

Thanks in advance.
Tunc

Nikolay Elenkov said…
Glad you found this post useful.

For 1), I don' know of any solution. Once you receive an APDU, it will block waiting for the next one and you cannot really interrupt it. Look at the latest source in CM, maybe something has been done about that. As for being much faster, that is expected, since you are running on the application processor, which is light-speed compared to the SIM.

As for 2), unfortunately I don't think it's very likely. HCE is not in 4.2 and the Nexus 4 is running a completely different NFC stack (the chip is not from NXP), so even the CM patch won't work anymore.
dragan said…
Hi,
Anyone tried this on Nexus7 and CM10?
Nikolay Elenkov said…
It does work with CM10 on Galaxy Nexus. The Nexus 7 has the same NFC chip, so theoretically it should work. Try it out.
Salvatore said…
Hi Nikolay,
I have downloaded the se-emulator and the se-pki-client. When I tap the phone on the nfc reader (ACS ACR122), the APDU logged (received?) by the phone aren't the same sent by the se-pki-client app. Furthermore, the se-pki-client doesn't receive any response to the select apdu command.
When se-pki-client starts and I tap the phone to the reader, I see the following log:
'Place phone/card on reader to start'.
When I remove the phone from the reader, the following exception are thrown:
'Exception in thread "main" java.lang.RuntimeException: javax.smartcardio.CardException: connect() failed
at org.nick.sepkiclient.Main.main(Main.java:105)
Caused by: javax.smartcardio.CardException: connect() failed
at sun.security.smartcardio.TerminalImpl.connect(Unknown Source)
at org.nick.sepkiclient.Main.waitForCard(Main.java:183)
at org.nick.sepkiclient.Main.main(Main.java:48)
Caused by: sun.security.smartcardio.PCSCException: SCARD_E_READER_UNAVAILABLE
at sun.security.smartcardio.PCSC.SCardConnect(Native Method)
at sun.security.smartcardio.CardImpl.(Unknown Source)
... 3 more'

Below the logs on phone side:
'D/MainActivity(1410): onResume()
D/PkiApplet(1410): Started applet thread 'PKI applet thread#139'
D/MainActivity(1410): Acquiring wakelock
D/PkiApplet(1410): [PKI applet thread#139] --> 9000
D/PkiApplet(1410): [PKI applet thread#139] <-- 00A4040009A00000039742544659
E/PkiApplet(1410): Invalid AID: 00A4040009A00000039742544659
D/PkiApplet(1410): [PKI applet thread#139] --> 6A82
D/PkiApplet(1410): [PKI applet thread#139] <-- 00A4040009A00000030800001000'

Have you some suggestions??

Thanks in advance,
Salvatore
Nikolay Elenkov said…
What device and CM are you using? Does your ACR122 work with regular cards? Not sure where the 00A4040009A00000039742544659 comes from, are you running something else that might be accessing the reader on your computer?
Salvatore said…
I am using Nexus S and CM 10.0.0-crespo. The ACR122 works fine with all regular cards and the se-pki-client is the only software that accesses to nfc reader.
I use windows7.

Thanks,
Salvatore
Nikolay Elenkov said…
Try with a newer CM version. Some of the early card emulation patches had a problem coexisting with Google Wallet, so you might want to try uninstalling it if it is installed.
Manuel Stahl said…
Thanks for that awesome tutorial. Do you know if anyone is working on a solution for the Nexus 4 (Broadcom BCM20793) or if at least the chip supports card emulation mode?
Nikolay Elenkov said…
Glad you find it useful. I haven't really looked into it, but at least there doesn't seem to be any related patches from the original author in CM's gerrit (http://review.cyanogenmod.org/#/q/owner:%22Doug+Yeager%22,n,z). I don't currently have any info on the BCM chip either, sorry.
Hi Nikolay, is LLCP emulation not possible at all with PN544 on Nexus S? This would allow usable Mifare Classic emulation on Android. If you have a look at the PN544 specification [0], it actually mentions being able to emulate Mifare.

[0] http://www.nxp.com/documents/leaflet/75016890.pdf
Nikolay Elenkov said…
Not sure what you want to do, but this post is about *software* card emulation. At least the referenced patch does not support emulating Mifare, it works at the ISO 14443-4 level.
Hi Nikolay, apologies for the confusion and to be off-topic. My goal is to be able to emulate Mifare classic cards with Android either by software or through SE. PN544's specification [0] in my understanding clearly says that it's possible. Linux also has a proper PN544 [1] driver. If we write a JNI and/or a custom NFC.apk which talks to PN544, shouldn't we be able to emulate MFC?

[1] http://lxr.free-electrons.com/source/drivers/nfc/pn544.c?v=3.0
Nikolay Elenkov said…
Google Wallet does it, so it is definitely possible (see Wallet articles on the blog). As far as I know the SE comes with a MIFARE4Mobile manager applet that lets you set up Mifare emulation. You can get the details from NXP, but you need to sign an NDA. Getting the keys for a commercial SE (such as the one in the Nexus devices) is another matter altogether: unless you partner up with Google you probably can'.
Many thanks. Your articles are very useful. I have already started reading the Google wallet article.
jdev said…
This comment has been removed by the author.
jdev said…
This comment has been removed by the author.
jdev said…
This comment has been removed by the author.
jdev said…
Got the solution here: Your invalid aid is sent by Windows 7 (see http://de.scribd.com/doc/89256105/Sc-minidriver-Specs-V7 on page 129)

First possibility: Do not use Windows 7 ;)

Second possibility (worked for me as well): Get exclusive access to the card:


System.out.println("Place phone/card on reader to start");
Card card = waitForCard(terminals);
card.beginExclusive(); // <-- add this line

See also http://docs.oracle.com/javase/6/docs/jre/api/security/smartcardio/spec/javax/smartcardio/Card.html#beginExclusive%28%29
Nikolay Elenkov said…
That makes sense, Crypto API is checking whether the card has a supported minidriver applet. Locking the card should solve this and similar problems, I will add it to the sample code. Thanks for posting your findings.
Anton said…
Hi Nikolay,
I am currently using a rooted Nexus 4 with Cyanogen Mod 10.1 running. Also using a VivoPay 4800 Card Reader.

I have been able to get access to the secure element and activate card emulation using the nfc_extras package through reflection. I have also added my app to nfcee_access.xml. My debugger is showing me NFC-EE ON and NFC-C ON when the app runs and all seems to working fine.

The problem occurs when I try to communicate with the card reader. The reader detects the phone upon contact and beeps twice (suppose to beep once when successful), but the phone does not detect anything whatsoever. I expected either onResume() or onNewIntent() to be called when the reader is brought into close contact, but that does not happen. In fact, nothing at all appears in the debugger. Google Wallet on the other hand works fine with the reader and it respons back with the selected AID of the card reader.

I would like to send a command using transceive upon the tech being discovered. My question is, how does the phone detect the card reader when it is near by? How can I initiate/trigger the communication between the two?
Nikolay Elenkov said…
The Nexus 4 uses a completely different NFC controller (by Broadcom) and drivers, so this is most probably not supported (yet).
Anton said…
Ok that makes sense. Just tried my code with a Galaxy Nexus, and it works perfectly.

Thank you for the many blogposts and reply, you have been a great help!
Mark Tsirlin said…
Hello,

I'm trying to explore EMV Contactless as a part of my dissertation in University?
Can I use your source code and modify it. Appropriate reference will be included.
Nikolay Elenkov said…
All code is Apache licensed so you an do anything permitted by the license (pretty much anything except claiming you wrote it). So go ahead :)
Hi Nikolay,

I'm struggling with my phone emulating a 14443 Type B card. I read your documentation (compliments) and used your source as the base for my app. However, when I present the phone (galaxy SIII w/CM10.1) to the reader I just can't seem to intercept the event/Intent.
The phone DOES send an ATP to the reader, which actually is:
11 e1 13 01 02 10 21 02 01 00 91 7d de 6d 00 00 00 00 33 81 84 00 b5 8a
which is a pure Type B card answer to poll.
On the device (looking at LogCat) nothing seems to happens, although earlier I do see;
06-22 22:29:17.160: D/NfcDispatcher(2528): Set Foreground Dispatch.
Probably I'm missing something here. Do you have *any* idea what is happening?
Thank you very much for any help.

Tony.
Nikolay Elenkov said…
Does it work with IsoPcdA? Does your reader work with IsoPcdB at all? Since this works on a higher level, there is really no difference which underlying tech you use, so if A works just works that. Unless you are trying to support a reader that only does B, of course.
My reader works with IsoPcdB only, basically. It's a proprietary motorola reader which does not support the different modulation of type A (yes, it is very old). I should try with a reader that supports A also, I guess.
Reading some more last night (particularly your article on the secure element access) can it be that the phone's secure element is talking to the reader, and software doesn't even come into play here? SOMEONE is talking to the reader. As shown above, I can trace the reader at low level.
I'm sorry if these seem ignorant questions, I come from the field of card readers and smartcards (public transportation), but android and smart phones are really new to me. What I'm trying to achieve here is have the phone talk to the legacy reader. I'm not trying to do anything fancy (yet), just have the reader detect the phone (which it seems to do) and send from the phone some apdu when it fires the Found Reader! event (which I am clearly missing).

Thanks again,
tony.
Nikolay Elenkov said…
I see. Are you sure your reader can be used for APDU based communication? As for who might be talking to the reader, do you have Google Wallet installed on that phone? That is about the only (common) app that activates card emulation on production devices.
First off, thank you for your prompt replies.
The reader is a standard reader which does talk 14443 with other cards (through adpu exchange) and I don't have Google Wallet installed. Just a clean CM10.1 and gapps-jb-20130301.
It is definitely the app that activates card emulation, because if I don't start it, the reader does not detect the phone. Btw; what exactly activates the card emulation in your app? Is it the enableForegroundDispatch() with the PcdB tech?
Problem is only that I don't get an onNewIntent() call when the phone gets into the field, and the reader detects it.

Thanks again,
tony.
Nikolay Elenkov said…
Foreground dispatch has been overloaded to enable card emulation in the lower level driver. So effectively starting the app should activate software card emulation. Do you have IsoPcdB in filter_nfc.xml? (the sample project comes with IsoPcdA only).
Yes I have, and substituted all other occurrences with IsoPcdB.
Look, I really don't want to bother you too much. If you want I can send you the zipped project for a quick look. It is really a reduced version of your application, with all the PKI stuff removed. Other than that, I you don't see anything fundamentally wrong with the concept, I'll just try and debug further, and see where I get.
I just tried to substitute the foreground dispatch to the form:
adapter.enableForegroundDispatch(this, pendingIntent, null, null);
I get a whole bunch of the following when presenting the phone to the reader:
06-23 17:41:32.595: W/NfceeAccess(5833): denied NFCEE access for it.point44.vvcard with signature: ....
Adapting the signature in the nfcee_access.xml file will say "GRANTED", but it still doesn't change the behavior with onNewIntent(). Is this significant?

Thanks a lot,
Tony.
Nikolay Elenkov said…
This is for accessing the embedded secure element, it does not affect software emulation. I think this might be a problem with reader and/or device compatibility, not sure looking at the project will help. Try with another device and/or reader first.
I tried with three other readers (ACS ACR 122, SCM SDI011 and ASK RDR417) with the same results. The phone (Samsung Galaxy S3 I9300) has -as far as I know- the standard PN544.
I just can't figure it out, the phone DOES send a correct type B sequence to the reader(s), but the phone just won't fire off an onNewIntent(). Well, such is life.

Thanks for all your help,
Tony.
neco git said…
Hi Nikolay,
Thanks for your valuable explanations. I have a question, I am planning to develop a prototype that has the ability to read from smartcard and also phone. In the prototype, there are a nfc reader connecting to the pc, a smartphone, and a smartcard. Which smartcard and smartcard reader is the easiest(also unproblematic) one for this? I was going to try with Mifare but you said Mifare is not working with card emulation. Which card type can you suggest? The model and platform do not matter. You may say any platform rather than Android. Thank you.
Joe said…
Thanks for this guide, it's great. I've just implemented an EMV compliant card application on my Nexus S using this as the basis.
neco git said…
Hi again,
Does anyone know that will it work with HTC One or Galaxy S4? If not, what is your recomm for the newest device that will work?
James said…
Fantastic post, thanks for this! The code worked fine for me, and I have a question about a similar use-case. We would like to access the UICC on the device, avoiding the PKCS#15 certificate checks which Open Mobile implements (so that APDU's go straight to the SIM as they do over external NFC devices). Do you know if cyanogenmod supports this interaction? Do you have any other suggestions or links?
AGUEROUAZ Ali said…
thanks alot for this tutorial.
i am working with slc011 reader, and i'am using your code but it didnt work is the probleme with this kind of reader because i saw that you are working with the AC.. reader.
Doug Yeager said…
Guys, this is such a great post and thread, lets keep it going! please see simplytapp website to get a whole new toolset for creating your own javacard applet and leveraging hce to deliver it. It is pki gp/javacard based. We are emplementing this tool set to make things more useful st the nfc pos. We will post applet examples like visa snd mastercard as we have time, but now u can release your own applet without buying a telco :)
Hi Nikolay,

Thanks for your detail explanation on how to emulate a smart card with CM9.1. However, do you think its possible to emulate a smart card without CM? As I am having a project for a NFC android phone to communicate with readers that through ISO7816 but SE seems cannot be skipped even security is not my concern. Just like SimplyTapp that it doesn't have any SE in the device but in cloud and no CM is used. That means technically it can be done if I can emulate the "cloud SE" like SimplyTapp. Do you think it works? Thanks and again thanks for your sharing.
Chaios Lee said…
I used Acr1251 rhe smartcardio happyeader and sony acro s(hikari) to try this, It doesn't works at sometime.
The client: Card card = waitForCard(terminals) don't work. I think the progress is run the client first,then wait me to push the phone on....the client don't wait. So i play the phone on the reader first then run the client and i can't keep it happy. so I let the code byte[] cmd = transceive(new byte[] { (byte) 0x90, 0x00 }); run more times, it works at some time.

I think there would be some problems in javax.smartcardio, my windows 7,and my new acsReader, I had try some windows SCardGetStatusChange() code, It can wait my card, but it seemly the phone can't paly as a real card, it can't response the reader intime。
roman hossain said…
The actual contents should be ignored by the NFC subsystem, so it shouldn't matter. What the comment means is that smartcardio will complain if you send less that two bytes. In any case, you should test with an actual POS terminal to see how it behaves.
http://www.mifarecards-rfid.com
Vega Hsieh said…
hi,I have a problem with HCE. I downloaded a sample code from https://github.com/grundid/host-card-emulation-sample. I build it and put it in google Nexus 5. I send the APDU to select AID and it returns successful return code. But I can't get successful return code when I put the same APP in Sony Xperia ZL. If I send APDU FFCA0000 to the two phones, they send back the UID. Can anyone tell me why I can't get successful return code when I send Select AID to the Sony Xperia ZL?
Unknown said…
This comment has been removed by the author.
MrBoghib said…
This comment has been removed by the author.
MrBoghib said…
Hi Nikolay
Sorry a litlle bit of topic
I like to know if a card like ATR14w , 125 khz modulatian ASK ,is possible to emulate on android ,knowing android it is working on 13,56 mhz ?

Popular posts from this blog

Password storage in Android M

Decrypting Android M adopted storage

Unpacking Android backups