Accessing the embedded secure element in Android 4.x

After discussing credential storage and Android's disk encryption, we'll now look at another way to protect your secrets: the embedded secure element (SE) found in recent devices. In the first post of this three part series we'll give some background info about the SE and show how to use the SE communication interfaces Android 4.x offers. In the second part we'll try sending some actual commands in order to find out more about the SE execution environment. Finally we will discuss Google Wallet and how it makes use of the SE.

What is a Secure Element and why do you want one? 

A Secure Element (SE) is a tamper resistant smart card chip capable of running smart card applications (called applets or cardlets) with a certain level of security and features. A smart card is essentially a minimalistic computing environment on single chip, complete with a CPU, ROM, EEPROM, RAM and I/O port. Recent cards also come equipped with cryptographic co-processors implementing common algorithms such as DES, AES and RSA. Smart cards use various techniques to implement tamper resistance, making it quite hard to extract data by disassembling or analyzing the chip. They come pre-programmed with a  multi-application OS that takes advantage of the hardware's memory protection features to ensure that each application's data is only available to itself. Application installation and (optionally) access is controlled by requiring the use of cryptographic keys for each operation.

The SE can be integrated in mobile devices in various form factors: UICC (commonly known as a SIM card), embedded in the handset or connected to a SD card slot. If the device supports  NFC the SE is usually connected to the NFC chip, making it possible to communicate with the SE wirelessly. 

Smart cards have been around for a while and are now used in applications ranging from pre-paid phone calls and transit ticketing to credit cards and VPN credential storage. Since an SE installed in a mobile device has equivalent or superior capabilities to that of a smart card, it can theoretically be used for any application physical smart cards are currently used for. Additionally, since an SE can host multiple applications, it has the potential to replace the bunch of cards people use daily with a single device. Furthermore, because the SE can be controlled by the device's OS, access to it can be restricted by requiring additional authentication (PIN or passphrase) to enable it. 

So a SE is obviously a very useful thing to have and with a lot of potential, but why would you want to access one from your apps? Aside from the obvious payment applications, which you couldn't realistically build unless you own a bank and have a contract with Visa and friends, there is the possibility of storing other cards you already have (access cards, loyalty cards, etc.) on your phone, but that too is somewhat of a gray area and may requiring contracting the relevant issuing entities. The main application for third party apps would be implementing and running a critical part of the app, such as credential storage or license verification inside the SE to guarantee that it is impervious to reversing and cracking. Other apps that can benefit from being implemented in the SE are One Time Password (OTP) generators and, of course PKI credential (i.e., private keys) storage. While implementing those apps is possible today with standard tools and technologies, using them in practice on current commercial Android devices is not that straightforward. We'll discuss this in detail the second part of the series, but let's first explore the types of SEs available on mobile devices, and the level of support they have in Android. 

Secure Element form factors in mobile devices

As mentioned in the previous section, SEs come integrated in different flavours: as an UICC, embedded or as plug-in cards for an SD card slot. This post is obviously about the embedded SE, but let's briefly review the rest as well. 

Pretty much any mobile device nowadays has an UICC (aka SIM card, although it is technically a SIM only when used on GSM networks) of some form or another. UICCs are actually smart cards that can host applications, and as such are one form of a SE. However, since the UICC is only connected to the basedband processor, which is separate from the application processor that runs the main device OS, they cannot be accessed directly from Android. All communication needs to go through the Radio Interface Layer (RIL) which is essentially a proprietary IPC interface to the baseband. Communication to the UICC SE is carried out using special extended AT commands (AT+CCHO, AT+CCHC, AT+CGLA as defined by 3GPP TS 27.007), which the current Android telephony manager does not support. The SEEK for Android project provides patches that do implement the needed commands, allowing for communicating with the UICC via their standard SmartCard API, which is a reference implementation of the SIMalliance Open Mobile API specification. However, as most components that talk directly to the hardware in Android, the RIL consists of an open source part (rild), and a proprietary library (libXXX-ril.so). In order to support communication with the UICC secure element, support for this needs to be added to both to rild and to the underlying proprietary library, which is of course up to hardware vendors. The SEEK project does provide a patch that lets the emulator talk directly to a UICC in an external PC/SC reader, but that is only usable for experiments. While there is some talk of integrating this functionality into stock Android (there is even an empty packages/apps/SmartCardService directory in the AOSP tree), there is currently no standard way to communicate with the UICC SE through the RIL (some commercial devices with custom firmware are reported to support it though).

An alternative way to use the UICC as a SE is using the Single Wire Protocol (SWP) when the UICC is connected to a NFC controller that supports it. This is the case in the Nexus S, as well as the Galaxy Nexus, and while this functionality is supported by the NFC controller drivers, it is disabled by default. This is however a software limitation, and people have managed to patch AOSP source to get around it and successfully communicate with UICC. This has the greatest potential to become part of stock Android, however, as of the current release (4.1.1), it is still not available. 

Another form factor for an SE is an Advanced Security SD card (ASSD), which is basically an SD card with an embedded SE chip. When connected to an Android device with and SD card slot, running a SEEK-patched Android version, the SE can be accessed via the SmartCard API. However, Android devices with an SD card slot are becoming the exceptions rather than the norm, so it is unlikely that ASSD Android support will make it to the mainstream.

And finally, there is the embedded SE. As the name implies, an embedded SE is part of the device's mainboard, either as a dedicated chip or integrated with the NFC one, and is not removable. The first Android device to feature an embedded SE was the Nexus S, which also introduced NFC support to Android. Subsequent Nexus-branded devices, as well as other popular handsets have continued this trend. The device we'll use in our experiments, the Galaxy Nexus, is built with NXP's PN65N chip, which bundles a NFC radio controller and an SE (P5CN072, part of NXP's SmartMX series) in a single package (a diagram can be found here).

NFC and the Secure Element

NFC and the SE are tightly integrated in Android, and not only because they share the same silicon, so let's say a few words about NFC. NFC has three standard modes of operation: 
  • reader/writer (R/W) mode, allowing for accessing external NFC tags 
  • peer-to-peer (P2P) mode, allowing for data exchange between two NFC devices 
  • card emulation (CE) mode, which allows the device to emulate a traditional contactless smart card 
What can Android do in each of these modes? The R/W mode allows you to read NDEF tags and  contactless cards, such as some transport cards. While this is, of course, useful, it essential turns your phone into a glorified card reader. P2P mode has been the most demoed and marketed one, in the form of Android Beam. This is only cool the first couple of times though, and since the API only gives you higher-level access to the underlying P2P communication protocol, its applications are currently limited. CE was not available in the initial Gingerbread release, and was introduced later in order to support Google Wallet. This is the NFC mode with the greatest potential for real-life applications. It allows your phone to be programmed to emulate pretty much any physical contactless card, considerably slimming down your physical wallet in the process.

The embedded SE is connected to the NFC controller through a SignalIn/SignalOut Connection (S2C, standardized as NFC-WI) and has three modes of operation: off, wired and virtual mode. In off mode there is no communication with the SE. In wired mode the SE is visible to the Android OS as if it were a contactless smartcard connected to the RF reader. In virtual mode the SE is visible to external readers as if the phone were a contactless smartcard. These modes are naturally mutually exclusive, so we can communicate with the SE either via the contactless interface (e.g., from an external reader), or through the wired interface (e.g., from an Android app). This post will focus on using the wired mode to communicate with the SE from an app. Communicating via NFC is no different than reading a physical contactless card and we'll touch on it briefly in the last post of the series.

Accessing the embedded Secure Element

This is a lot of (useful?) information, but we still haven't answered the main question of this entry: how can we access the embedded SE? The bad news is that there is no public Android SDK API for this (yet). The good news is that accessing it in a standard and (somewhat) officially supported way is possible in current Android versions.

Card emulation, and consequently, internal APIs for accessing the embedded SE were introduced in Android 2.3.4, and that is the version Google Wallet launched on. Those APIs were, and remain, hidden from SDK applications. Additionally using them required system-level permissions (WRITE_SECURE_SETTINGS or NFCEE_ADMIN) in 2.3.4 and subsequent Gingerbread releases, as well as in the initial Ice Cream Sandwich release (4.0, API Level 14). What this means is that only Google (for Nexus) devices, and mobile vendors (for everything else) could distribute apps that use the SE, because they need to either be part of the core OS, or be signed with the platform keys, controlled by the respective vendor. Since the only app that made use of the SE was Google Wallet, which ran only on Nexus S (and initially on a single carrier), this was good enough. However, it made it impossible to develop and distribute an SE app without having it signed by the platform vendor. Android 4.0.4 (API Level 15) changed that by replacing the system-level permission requirement with signing certificate (aka, 'signature' in Android framework terms) whitelisting at the OS level. While this still requires modifying core OS files, and thus vendor cooperation, there is no need to sign SE applications with the vendor key, which greatly simplifies distribution. Additionally, since the whiltelist is maintained in a file, it can easily be updated using an OTA to add support for more SE applications.

In practice this is implemented by the NfceeAccessControl class and enforced by the system NfcService. NfceeAccessControl reads the whilelist from /etc/nfcee_access.xml which is an XML file that stores a list of signing certificates and package names that are allowed to access the SE. Access can be granted both to all apps signed by a particular certificate's private key (if no package is specified), or to a single package (app) only. Here's how the file looks like:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
  <signer android:signature="30820...90">
    <package android:name="org.foo.nfc.app">
  </package></signer>
</resources>

This would allow SE access to the 'org.foo.nfc.app' package, if it is signed by the specified signer. So the first step to getting our app to access the SE is adding its signing certificate and package name to the nfcee_access.xml file. This file resides on the system partition (/etc is symlinked to /system/etc), so we need root access in order to remount it read-write and modify the file. The stock file already has the Google Wallet certificate in it, so it is a good idea to start with that and add our own package, otherwise Google Wallet SE access would be disabled. The 'signature' attribute is a hex encoding of the signing certificate in DER format, which is a pity since that results in an excessively long string (a hash of the certificate would have sufficed) . We can either add a <debug/> element to the file, install it, try to access the SE and get the string we need to add from the access denied exception, or simplify the process a bit by preparing the string in advance. We can get the certificate bytes in hex format with a command like this:

$ keytool -exportcert -v -keystore my.keystore -alias my_signing_key \
-storepass password|xxd -p -|tr -d '\n'

This will print the hex string on a single line, so you might want to redirect it to a file for easier copying. Add a new <signer> element to the stock file, add your app's package name and the certificate hex string, and replace the original file in /etc/ (backups are always a good idea). You will also need to reboot the device for the changes to take effect, since file is only read when the NfcService starts.

As we said, there are no special permissions required to access the SE in ICS (4.0.3 and above) and Jelly Bean (4.1), so we only need to add the standard NFC permission to our app's manifest. However, the library that implements SE access is marked as optional, and to get it loaded for our app, we need to mark it as required in the manifest with the <uses-library> tag. The AndroidManifest.xml for the app should look something like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.foo.nfc.app"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.NFC" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <uses-library
            android:name="com.android.nfc_extras"
            android:required="true" />
    </application>
</manifest>

With the boilerplate out of the way it is finally time to actually access the SE API. Android doesn't currently implement a standard smart card communication API such as JSR 177 or the Open Mobile API, but instead offers a very basic communication interface in the NfcExecutionEnvironment (NFC-EE) class. It has only three public methods:

public class NfcExecutionEnvironment {
    public void open() throws IOException {...}

    public void close() throws IOException {...}

    public byte[] transceive(byte[] in) throws IOException {...}
}

This simple interface is sufficient to communicate with the SE, so now we just need to get access to an instance. This is available via a static method of the NfcAdapterExtras class which controls both card emulation route (currently only to the SE, since UICC support is not available) and NFC-EE management. So the full code to send a command to the SE becomes:

NfcAdapterExtras adapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(context));
NfcExecutionEnvironment nfceEe = adapterExtras.getEmbeddedExecutionEnvironment();
nfcEe.open();
byte[] response = nfcEe.transceive(command);
nfcEe.close();

As we mentioned earlier however, com.android.nfc_extras is an optional package and thus not part of the SDK. We can't import it directly, so we have to either build our app as part of the full Android source (by placing it in /packages/apps/), or resort to reflection. Since the SE interface is quite small, we opt for ease of building and testing, and will use reflection. The code to get, open and use an NFC-EE instance now degenerates to something like this:

Class nfcExtrasClazz = Class.forName("com.android.nfc_extras.NfcAdapterExtras");
Method getMethod = nfcExtrasClazz .getMethod("get", Class.forName("android.nfc.NfcAdapter"));
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(context);
Object nfcExtras = getMethod .invoke(nfcExtrasClazz, adapter);

Method getEEMethod = nfcExtras.getClass().getMethod("getEmbeddedExecutionEnvironment", 
                    (Class[]) null);
Object ee = getEEMethod.invoke(nfcExtras , (Object[]) null);
Class eeClazz = se.getClass();
Method openMethod = eeClazz.getMethod("open", (Class[]) null);
Method transceiveMethod = ee.getClass().getMethod("transceive",
                    new Class[] { byte[].class });
Method closeMethod = eeClazz.getMethod("close", (Class[]) null);

openMethod.invoke(se, (Object[]) null);
Object response = transceiveMethod.invoke(se, command);
closeMethod.invoke(se, (Object[]) null);

We can of course wrap this up in a prettier package, and we will in the second part of the series. What is important to remember is to call close() when done, because wired access to the SE blocks contactless access while the NFC-EE is open. We should now have a working connection to the embedded SE and sending some bytes should produce a (error) response. Here's a first try:

D/SEConnection(27318): --> 00000000
D/SEConnection(27318): <-- 6E00


We'll explain what the response means and show how to send some actually meaningful commands in the second part of the article.

Summary

A secure element is a tamper resistant execution environment on a chip that can execute applications and store data in a secure manner. An SE is found on the UICC of every Android phone, but the platform currently doesn't allow access to it. Recent devices come with NFC support, which is often combined with an embedded secure element chip, usually in the same package. The embedded secure element can be accessed both externally via a NFC reader/writer (virtual mode) or internally via the NfcExecutionEnvironment API (wired mode). Access to the API is currently controlled by a system level whitelist of signing certificates and package names. Once an application is whitelisted, it can communicate with the SE without any other special permissions or restrictions.

Comments

Good article. The SIM Alliance API works "out of the box" on a commercial Samsung Galaxy S3, http://code.google.com/p/seek-for-android/wiki/UsingSmartCardAPI
You just need a valid SIM with the correct PKCS#15 access control rules set for your applet, http://code.google.com/p/seek-for-android/wiki/AccessControlIntroduction or an Access Rule Application (ARA) that allows all apps to send APDUs to any AIDs.
Nikolay Elenkov said…
Thanks. I guess we are going to see more device that work with UICC as more carrier-driven payment services are rolled out. Still, I don't think you will have access to the Card Manager keys for a 'real' operator SIM. What SIM are you using?
Hao said…
Great article! But I think the second way to use SIM as SE is not correct, actually SWP should be part of first way: both SWP and modified RIL are mandatory to make SIM as SE.

Nikolay Elenkov said…
The point here is that you use SWP to connect the SIM to the NFC controller and then communicate to it through the NFC controller (it looks similar to the embedded SE). You can communicate to the SIM without an NFC controller though -- that's basically how phones authenticate to the GSM network. So you can talk to the SIM through the RIL without the need for an NFC controller or a SWP connection.
Hao said…
You mean NFC controller as a router between SIM and the app? I am not sure, can you show some evidence?
Nikolay Elenkov said…
Yes, you can select between embedded SE and SIM. Check libnfc-nxp and Nfc.apk source code. Not enabled by default, but some people have done it.
Vinz said…
Great article, thanks. I've added the signature obtained with but am still getting "02-25 11:54:47.348: E/TestSEAccess(6485): Error: /etc/nfcee_access.xml denies NFCEE access to ....". Any idea? Also, I notice that the signature I get is different than the one obtained with "$ keytool -exportcert -v -keystore my.keystore -alias my_signing_key \-storepass password|xxd -p -|tr -d '\n'"
Thanks for your help.
Nikolay Elenkov said…
Make sure you are using the same keystore for signing your app. Also, if you add the element to nfcee_access.xm, the signature (certificate bytes really), will be written to the log (logcat), so you can just copy it from there.
shen747 said…
Hi Nikolay,

I used the APDU : 00 A4 04 00 0E A0 00 00 04 76 30 30 00 to select the Mifare Manager but instead of the 90 00(success) APDU response it gives me the 6A 82 (File not found.) response. Could you please help me out here ?. I'm using a GS3 running JB for testing. But the CPLC APDU command works fine.
Nikolay Elenkov said…
The Mifare applet may not be available on all devices. I don't have a GS3, so can't really check it. Does Google Wallet work properly on that device, including the loyalty cards feature?
HI,
I am interested in Developing an application for Android 4.x+. However, which mobile phone will be the best suit for such an application. I would however required storing data on the secure element itself by re-creating the steps shown in this tutorial. Samsung S2,S3 or S4? .
CJ
Nikolay Elenkov said…
I don't own any of those phones, but in order to store anything on the SE, you need the Card Manager key, which are not available for commercial devices.
Thank you. Which mobile phones would you prefer in using, when trying to access and store data on the Embedded Secure Element?
Vladimir Litman said…
Hi,
I'm interesting if you have an idea how to obtain such system level certificate from the manufacturer. We developing an OMA-DM android client/server for remote management of the smartphones and we using system level.
Beowolf said…
This comment has been removed by the author.
Beowolf said…
I wonder if anyone has looked into the Google Host Card Emulation? Kitkat 4.4 has a secure element that you can exchange ISO7816-4 APDUs with. I am looking for any code that accesses this secure element, and exchanges keys with it. Can anyone help?
Nikolay Elenkov said…
HCE has nothing to do with secure elements, it's implemented in software, just like all Android apps. There is an official Google sample that emulates loyalty cards, see the repository below and the 'Emulating a PKI applet' post for details:

https://github.com/nelenkov/virtual-pki-card/tree/master/hce-pki
Mazlum Derse said…
Hi,
I am working on Mobile Payment. I have a problem about Secure Element.
How can I install a Java Card Applet to Embedded Secure Element of Samsung Galaxy S4?
Hi Nikolay,

Do you mean that we can access SE without rooting phone? Is it possible to write an application which can store NFC tag to SE without rooting phone?
Thanks a lot in advance.
Braj
Nikolay Elenkov said…
No, read this and the next few posts for details.
Kuan Shu said…
This comment has been removed by the author.
Kuan Shu said…
great article, As i read from the seek for android(https://code.google.com/p/seek-for-android/wiki/DeviceDetails), "It is required to deploy a PKCS#15 Access Control file system on the SIM card, otherwise no APDU access is granted. " what does that mean? I patched smartcard api to cm10.2 and flashed it to i9300 everything is fine, but when i try to open a default channel on uicc terminal it reply access denied.
Nikolay Elenkov said…
It means you need to be able to install applets on the UICC in order for this to work. Probably not going to happen with a commercial SIM.
Kuan Shu said…
but my i9300 run official ROM can connect to the AP with eap sim authentication, so the official ROM can somehow access to the SIM card. I really want to know is it possible to do eap sim authentication as the official ROM do.
Nikolay Elenkov said…
Your app needs to be signed with the same key/certificate as the stock app. See the SEEK wiki for details:

https://code.google.com/p/seek-for-android/wiki/AccessControlIntroduction
Kuan Shu said…
This comment has been removed by the author.
Kuan Shu said…
does the command makes the SIM card run GSM algorithm to generate SRES Kc use basic channel or logical channel? My app's connection denied byAccess Control Enforcer because my app is not correctly signed and samsung's official ROM's wifimanager app is correctly signed? and what sign is correct is determined by Access Control Enforcer? where Acess Control Enforcer implemented? all in all is it possible to send command that makes the SIM card run GSM algorithm through smarcard api to SIM card? thnak you very much.
Nikolay Elenkov said…
Please read the documentation on the SEEK site. This should be obvious, but let me spell it out: this is a blog, and I cannot provide support for your private or corporate projects. Questions not related to the blog contents are largely ignored.
Zebibi said…
Hello Nikolay,
I have several applications that need the NFCEE_ADMIN permission and I sign them all with a single key. I noticed that if I add several times the same signature for different packages in the nfcee_access.xml file then only the first package listed in the file has its access granted. Do you confim this behaviour?
Is it possible to list several packages for the same signature, i.e do something like this:





?
Thanks in advance.
Nikolay Elenkov said…
Simply don't add the package attribute and list the key only once. See the comments in the AOSP nfcee_access.xml file and the related parser class for details.
Tom Cobb said…
Related question: Who "owns" the Secure Element and what does "ownership" mean? At a minimum I would guess that the owner simply controls the keys that allow access to and use of the SE. Is there any indication that legal ownership extends to the SE itself?
Nikolay Elenkov said…
I can't comment on the legal side of things, but generally you 'own' the SE if you have the keys necessary to install and delete applets. The owner could be the MNO, phone manufacturer, a TSM, etc. See the next post for some discussion of this topic.
Mehdi Noukra said…
Hi Nikolay,
What a good article you've writen. However, I'm facing a difficulty trying to " build my app as part of the full Android source (by placing it in /packages/apps/)". Can please provide more details regarding this step.
Thanks in advance.
Unknown said…
Hey Nik,

I am not sure if this thread is still alive, however, let me throw my quick question here

Is it possible to know if a device has got SE embedded from user application? One dumb way to check this by ensuring that /etc/nfcee_access.xml file is present or not. Is there any other cool way ?
Nikolay Elenkov said…
There is no API for this, you can probably find out the model of the NFC controller by inspecting dmesg or via /proc or /sys, but that would be hardware specific.
Mehtab Khan said…
Hi Nikolay,
Actually i m working on Android new Project in which I have to fetch card information from Google Wallet through NFC in my Android application. How can I start it in my android application?
Your blog articles are always awesome and I am a long time follower. An enormous thanks to you for explaining many of us the intricate details of Android internals. I would like to buy a hard copy of your various chapters.
Nikolay Elenkov said…
Thanks! Not sure what you mean by 'hard copy of chapters', but you can get my book from No Starch, Amazon, or O'Reilly.
annu said…
Hi Nikolay

Do you have any idea how can we install java card applet on embedded secure element present in galaxy s3?
Nikolay Elenkov said…
You have to work with the phone manufacturer or carrier to get access to the SE.

Popular posts from this blog

Password storage in Android M

Decrypting Android M adopted storage

Unpacking Android backups