Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

NFC - Card Emulation Primer

by BlackBerry Development Advisor (Retired) on ‎03-01-2012 01:26 PM - edited on ‎03-01-2012 01:26 PM by BlackBerry Development Advisor (13,881 Views)

Introduction

This article is part of a series intended to help developers wishing to exploit NFC in their BlackBerry® smartphone applications. Readers of this article should have some pre-existing knowledge of the fundamental architecture of NFC systems and be familiar with Java®. It would be beneficial to have read the first article in this series entitled: "NFC Primer for Developers". This article will look specifically at the issues, APIs and techniques involved in writing BlackBerry Java applications which are part of “NFC card emulation solutions” using a hardware secure element.

 

The Authors

This article was co-authored by Martin Woolley and John Murray both of whom work in the RIM Developer Relations team. Both Martin and John specialize in NFC applications development (amongst other things).

 

About this article

Some NFC applications involve “card emulation”. This is a term used to describe the use of an NFC enabled smartphone such as a BlackBerry® Bold™ 9900 to emulate some kind of physical smart card such as a payment card. In use cases like this, security is highly important and so the software component which emulates the physical smart card is typically implemented as an “applet” and installed in a “secure element” in either a UICC or embedded in the BlackBerry smartphone itself.

In the context of this article, “applet” means a smart card application, probably written using the Java Card APIs. If any of the other terms are new to you then we suggest you read the NFC Primer for Developers before proceeding further.

Note that this article has been written with the version 7.0 APIs in mind. From time to time we’ll mention 7.1 however.

 

Architecture and Terminology

BlackBerry NFC card emulation solutions will usually include a BlackBerry application, written in Java which works alongside and in conjunction with the corresponding applet in the secure element. We sometimes call these applications “service provider applications”. Their role is to provide a user interface and configuration capabilities relating to a particular, emulated card. You may also encounter the term “wallet”. A wallet is an application which acts as a catalogue of all emulated cards installed on a smartphone and provides various facilities to the user such as the ability to set defaults.

 

service_provider_apps.jpg

Figure 1 - Service provider applications and applets

 

Strictly speaking, the emulation of a particular type of card is the sole responsibility of the applet and for a significant proportion of use cases, the applet will function quite independently of any BlackBerry application. However, service provider applications will, from time to time, interact with an applet in the secure element. The basis of this interaction is ISO 7816-4 APDUs, formulated and handled using the Java JSR-177 API.

This article is primarily intended to help developers working on “service provider applications” and will explore the relevant APIs and coding techniques. It will not attempt to go into extensive detail regarding the development of card emulation applets themselves.

 

Sample Code

Throughout this article, code fragments have been included to help illustrate the issues and techniques being described. Generally, code has been simplified for inclusion in the article. For example, error handling, logging and null checking may have been removed. A full, working application with all source code called “NfcTransactionHandler” has been released with this article however and may be downloaded from our “Samples-for-Java” GitHub® repository, details of which may be found at the end of this article.

 

Interaction Model

The relationship between an application and the applet it communicates with using ISO-7816-4 APDUs is generally one of “master and slave” whereby the applet will do nothing unless it receives a request APDU from the application. On receipt of such a request, the applet will process it and return a response APDU. There’s an exception to this however.

 

Emulated cards will often execute high level operations generally referred to as “transactions”. An obvious example is making a payment. The lower level interactions which comprise the transaction take place between the PICC (Proximity Integrated Circuit Card) and PCD (Proximity Coupling Device). Note that in the context of BlackBerry smartphones and this article, the PICC is the BlackBerry smartphone with its NFC components and the PCD is the contactless reader that the smartphone is interacting with.

 

When a transaction has been executed by an applet, it may need to inform the service provider application with which it is associated that this is the case. This would enable, for example, the service provider application to display a message to the user indicating that their payment was successfully made. To do this, the applet may trigger an event known as an “EVT_TRANSACTION event”. Such events will be communicated to the “host terminal” in which applications are installed. In our case the “host terminal” is the BlackBerry application run-time environment. The system, on receipt of an EVT_TRANSACTION message will route it to the appropriate application for processing. The application may respond by displaying information to the user or by asking the applet for further details of the transaction by sending APDUs to it. We’ll look at the APIs involved in receiving transaction notifications and interacting with applets in the next section.

 

Note that the term EVT_TRANSACTION is used in specifications such as ETSI TS 102 622 which is entitled “Smart Cards; UICC - Contactless Front-end (CLF) Interface; Host Controller Interface (HCI)”.

 

evt_transaction.png

Figure 2 - EVT_TRANSACTION in a payment scenario

 

Figure 2 illustrates an EVT_TRANSACTION being communicated to a service provider application. How the system knows which application to notify is something we’ll discuss in a later section. The right hand side of the diagram also introduces the acronym “EMV”. EMV is the name of a standard which governs the authentication of credit and debit card transactions. It is attributed to Europay, Mastercard and VISA. It’s shown here as an example of the kind of “conversation” that might take place between an applet and reader which in this scenario would be a point of sale terminal with a contactless NFC interface.

 

Development Issues

Developers of service provider applications must be able to deal with a number of issues:

  • How to keep track of the status of the smartphone’s NFC service. The user may switch it on or off from the connections panel on their smartphone.
  • How and when to enable card emulation mode, one of the three modes of operation defined by the NFC Forum.
  • How to NFC route traffic from the PCD to the appropriate secure element. Remember, a BlackBerry NFC-enabled smartphone may have one or two secure elements available to it; one in the UICC and one embedded in the smartphone itself.
  • How to associate itself with a particular applet or applets in the secure element.
  • How to receive transaction notifications.
  • What steps to take to ensure your application can receive and respond to transaction notifications if it is not running or is in background.
  • How to interact with an applet in the secure element using ISO 7816-4.

Note that this article focuses primarily on the work which a developer of a BlackBerry application must do. MIDlet developers must address the same issues but work with some different APIs to do so (though there’s a high degree of overlap with the APIs used by BlackBerry apps). We’ll briefly look at these issues from the point of view of the MIDlet developer but to begin with we will concentrate on developers who are using the RIM APIs to develop their application. Such applications have a class which extends the UiApplication class whereas MIDlet developers will extend the MIDlet class.

 

Java Classes and Interfaces

Before we start to look at the issues listed above, let’s introduce the key classes and interfaces that we’ll be working with.

 

Name

Type

Description

NFCStatusListener

Interface

Receives notifications related to changes in NFC service information such as, for example, the service being switched off by the user.

NFCManager

Class

A singleton which provides a number of capabilities to manage the NFC service on the smartphone. This includes the ability to register an NFCStatusListener and to prompt the user to switch on NFC. Also defines a series of constants which are used in various scenarios.

SecureElement

Class

Represents a secure element on the smartphone. A SecureElement object will relate to either the UICC resident secure element or the device-embedded secure element.

SecureElementManager

Class

A singleton which provides access to SecureElement objects and the ability to control aspects of their behaviour.

TransactionListener

Interface

Receives notifications relating to transactions processed by applets in a secure element.

 

Figure 3 - Classes and Interfaces

 

Enabling Card Emulation Mode

Before the user can use their BlackBerry smartphone and your application as an emulated smart card and do something concrete such as pay for goods, you will need to switch the smartphone into card emulation mode and ensure the relevant NFC protocol traffic is routed to the secure element which contains the applet responsible for emulating the card in question. This is accomplished using the SecureElement class and the setTechnologyTypes method. Calling setTechnologyTypes requires certain parameters and these specify particular NFC protocol types and a device state for which traffic should be routed to the secure element that your SecureElement object represents. An example will help understand this:

 

// when the device is powered, route ISO14443 type B traffic to the SE in the SIM/UICC

SecureElement se = sem.getSecureElement(SecureElement.SIM);
se.setTechnologyTypes(SecureElement.BATTERY_ON_MODE, TechnologyType.ISO14443B);

  

Which protocol variant you choose to route to the secure element will depend on the capabilities of the NFC readers your application is designed to work with. Note that you can specify more than one protocol by combining TechnologyType constant values with the logical OR operator.

 

Receiving HCI Transaction Events

To receive notifications of transactions having been processed by an applet in a secure element, the service provider application must implement and register the TransactionListener interface.

 

When registering, the service provider application must indicate the applet or applets which it wishes to be associated with. This is achieved by specifying a list of Applet IDs (AIDs). An AID is a unique identifier for an applet, normally specified as a string of hexadecimal numbers or as an array of byte values. When registering a TransactionListener, the API allows us to specify a list of one or more AIDs in the form of a 2 dimensional byte array where each byte array contains an AID.

 

The TransactionListener interface has a single method, onTransactionDetected. The onTransactionDetected method is called by the system whenever a transaction event is raised by an applet associated with this application. The AID(s) of applet(s) responsible for the transaction are indicated in an argument to this method.

 

Figure 4 shows an implementation of TransactionListener. We’ll discuss the details in due course.

 

public class NfcTransHandlerApp extends UiApplication implements TransactionListener {

....

	public void onTransactionDetected(byte[][] aids) {
		int num_aids = aids.length;
		String aids_as_string = "";
		for (int i = 0; i < num_aids; i++) {
			String aid = ByteArrayUtilities.byteArrayToHex(aids[i]);
			aids_as_string = aids_as_string + "," + aid;
		}
		aids_as_string = aids_as_string.substring(1, aids_as_string.length());
		showDetailsScreen(aids_as_string);
		// exit because we'll be launched afresh when the next transaction occurs so no need to linger in the background
		if (transactionLaunch) {
			transactionLaunch = false;
			System.exit(0);
		}
	}

}

Figure 4 - Implementing TransactionListener

 

Figure 5 shows the key steps to registering a TransactionListener.

 

SecureElementManager sem = SecureElementManager.getInstance();
SecureElement se = sem.getSecureElement(SecureElement.SIM);

// if the SIM has no SecureELement our application cannot work
if (se == null) {
    Utilities.log("XXXX SecureElement(SIM) is null - exiting");
    // take suitable action
}

// register our app as a transaction listener
try {
    se.addTransactionListener(app,Constants.MY_AIDS);
} catch (NFCException e) {
    // see rule #2 below
    if (!e.getMessage().startsWith("TransactionListener has already been added")) {
	Utilities.log("XXXX exception when adding transaction listener: " + 
                           e.getClass().getName() + ":" + e.getMessage());
        // take suitable action
    }
}

// now that we’ve registered automatically, we can allow our application to exit

 Figure 5 - Registering a TransactionListener (simplified)

 

Note that not all SIMs contain a secure element and users may of course change the SIM in their smartphone. Consequently, checking for a value of null returned by getSecureElement(SecureElement.SIM) is a good idea.

 

Figure 6 shows the Constants.MY_AIDS constant used in the call to addTransactionListener(...).

 

    public static final byte[][] MY_AIDS = 
             {  
               { 0x6E, 0x66, 0x63, 0x74, 0x65, 0x73, 0x74, 0x30, 0x31 } 
             };

Figure 6 - AID constant definition

 

Note that card emulation must have been enabled before transaction events can be received and the enterEventDispatcher method must also have been called.

 

There are a number of rules which your code must comply with when using the TransactionListener interface. These are as follows:

 

  1. A TransactionListener must be associated with one or more AIDs.
  2. A distinct AID in a Secure Element must be associated with zero or 1 TransactionListener instances only. If one or more of the AIDs specified as a parameter to addTransactionListener has already been registered, none of the AIDs will be registered and an NFCException will be thrown.
  3. It is only possible to register a given TransactionListener instance once (even if specifying different AIDs each time)
  4. If a second application attempts to register as a TransactionListener for an AID for which a listener has already registered, the request will be rejected. This is managed on a per secure element (SE) basis. For example application 1 can register for AID 1:2:3 on the SIM while application 2 can register for AID 1:2:3 on the embedded SE.
  5. TransactionListener instances will only receive call backs for events relating to the AIDs for which they have registered.
  6. If an AID provided in addTransactionListener(...,...) has an invalid length (<5 or >16) an IllegalArgumentException will be thrown.
  7. If an application shuts down after registering a listener, the application will be restarted when a transaction occurs with the string "seTransactionListener" passed into the application as an argument to main( String [] args ). Your main method should include a code block for this argument value and call enterEventDispatcher() to ensure that the listener call back takes place.

 

Regarding rule #2, for some applications it may be valid that the AID(s) the application works with have already been registered, perhaps from a previous invocation of the application. As such you will either wish to avoid re-registering or to ignore exceptions arising from re-registering the same AID. However, at version 7.0 of the APIs there is no way to check in advance whether or not your TransactionListener has already been registered. As such, you must check the message attribute of any NFCException which is thrown when calling addTransactionListener to determine whether or not it was thrown as a consequence of the AID already having been registered. At version 7.1 of the BlackBerry NFC APIs, there is a new method in the SecureElement class, isTransactionListenerRegistered(byte [] aid) which you may call to pro-actively check before registering.

 

Application Entry Points

BlackBerry smartphone application developers will be familiar with the concept of application entry points. For those who are not, take a look at the following brief article on the subject:

 

http://supportforums.blackberry.com/t5/Java-Development/Set-up-an-alternate-entry-point-for-an-appli...

 

Application requirements will vary, but a typical approach to working with TransactionListener will involve three distinct entry points. These are as follows:

  1. Default entry point. Corresponds to the user having launched your application from the home screen. Typically this will result in a user interface being displayed.
  2. Auto-start entry point. This entry point is used by the system to automatically launch your application when the smartphone it is installed upon boots up. We’ll usually register our TransactionListener here. See Figure 7.
  3. Transaction received entry point. This entry point is used when the system launches your application due to the fact that a transaction event has been received from a secure element applet and your application, which had previously registered for transactions from this applet, was not running at the time. The system will pass an argument with the value “seTransactionListener” to your main method in this situation.

Entry point (2) must be explicitly defined by you in the application’s descriptor. The others exist by default and your responsibility is confined to coding for them in your application’s main method.

 

application_descriptor.png

Figure 7 - Alternate entry point for auto starting the application

 

Figure 8 illustrates the usual structure of the code in your main method. It is important to note that much code has been deliberately excluded from this fragment to allow the structure to be more easily understood. We’ll fill in the details as we proceed further on in the article and of course you should look at the full code sample from our GitHub repository as well.

 

public static void main(String[] args) {
  NfcTransHandlerApp app = new NfcTransHandlerApp();

  if (args.length > 0) {
    if (args[0].equals("auto")) {
    // Entry Point #2
      Utilities.log("XXXX auto starting NfcTransactionHandler");
      // register our app as a transaction listener
      // .... detail of registration steps not shown here....
      Utilities.log("XXXX TransactionListener is exiting and will be restarted when a transaction occurs");
    } else {
      if (args[0].equals("seTransactionListener")) {
    // Entry Point #3
        Utilities.log("XXXX launched by system to handle NFC transaction");
        app.enterEventDispatcher();		
      }
    }
  } else {
    // Entry Point #1
    Utilities.log("XXXX launched with no arguments");
    NfcTransScreen screen = NfcTransScreen.getInstance();
    app.pushScreen(screen);
    app.enterEventDispatcher();
  }
}

Figure 8 - Entry points and main method structure

 

We’ve already seen the kind of code which should be implemented for entry point #2 in Figure 5 above. Let’s now consider the other two entry points.

 

We’ll start with entry point #3, which is executed whenever our application gets launched by the system so that it can receive a call back to its TransactionListener interface. Transaction events destined for a TransactionListener are handled by the system as events on the event queue and so one of the things this entry point must do is call enterEventDispatcher() so that events are processed. This will allow the call to our TransactionListener’s onTransactionDetected method to be carried out by the system. It’s usual to also set a static boolean flag which indicates that we’re running as a consequence of the system launching the application and delivering a transaction event. This allows us to exit this application instance after dealing with the transaction event. There is no reason to keep that instance running, consuming resources.

 

The code is very simple and may look like that shown in Figure 9.

 

if (args[0].equals("seTransactionListener")) {
  Utilities.log("XXXX launched by system to handle NFC transaction");
  transactionLaunch=true;
  app.enterEventDispatcher();		
}

Figure 9 - seTransactionListener entry point

 

What happens in the onTransactionDetected method requires some explanation. Usually you will want to interact with the user, perhaps simply to indicate that a transaction was carried out due to them having “tapped” their BlackBerry on to a POS reader (note that you don’t actually need to “tap” your smartphone.... touching or hovering the smartphone close to the reader is enough!).

 

However, due to the way alternate entry points work, there are two issues to consider and address:

  1. When launching our application with the “seTransactionListener” argument (i.e. using entry point #3), the system will create a new instance of our application, running in its own process. BlackBerry developers familiar with other APIs such as the MDS push API will be recognise this behaviour.
  2. The separate application instance launched via the default entry point due to the user selecting the application’s icon on the home screen may or may not be already running.

So, when handling transactions, we need to pass the fact that a transaction occurred, together with the AIDs provided to us, to the foreground instance of our application. If it is not running then we need to launch it. If it is running but currently in background, we may want to switch it into the foreground to get the user’s attention.

 

Passing data between application instances is a well understood task for BlackBerry developers and there are a variety of ways of accomplishing this. In our code sample, we used the RuntimeStore object and implemented a thread in our foreground UI instance which monitors the RuntimeStore for relevant data appearing there.

 

Let’s take a look at some code fragments which address these points. First of all, the default entry point, which provides a UI to the user, starts a thread for monitoring the RuntimeStore for transaction data. It also places an object into the RuntimeStore which acts as a token to indicate that the UI is running.

 

public final class NfcTransScreen extends MainScreen implements Runnable {

  public void run() {
    boolean running = true;
    while (running) {
    try {
      RuntimeStore rts = RuntimeStore.getRuntimeStore();
      try {
        Object obj = rts.waitFor(NfcTransHandlerApp.PASSED_TO_UI_DATA_ID);
        if (obj != null) {
          String aids_received = (String) rts.remove(NfcTransHandlerApp.PASSED_TO_UI_DATA_ID);

          // do something with the data and then make sure the UI app is in foreground
          ......
          ......
          UiApplication.getApplication().requestForeground();
        }
      } catch (RuntimeException e) {
        Utilities.log("XXXX RunTimeException - probably timed out waiting for object in RTS");
      }
    } catch (Exception e) {
      Utilities.log("XXXX Exception in RTS loop: " + e.getClass().getName() + ":" + e.getMessage());
    }
  }

// called from our screen object’s constructor to indicate the UI app instance is running
  private void setUiRunningIndication() {
    Object ui_running_token = new Object();
    RuntimeStore rts = RuntimeStore.getRuntimeStore();
    rts.replace(Constants.UI_IS_RUNNING, ui_running_token);
  }
}

Figure 10 - UI instance waiting for transaction data

 

Let’s take another look at what we do in the onTransactionDetected method, first introduced in Figure 4 above and repeated here for convenience.

 

public class NfcTransHandlerApp extends UiApplication implements TransactionListener {

....

	public void onTransactionDetected(byte[][] aids) {
		int num_aids = aids.length;
		String aids_as_string = "";
		for (int i = 0; i < num_aids; i++) {
			String aid = ByteArrayUtilities.byteArrayToHex(aids[i]);
			aids_as_string = aids_as_string + "," + aid;
		}
		aids_as_string = aids_as_string.substring(1, aids_as_string.length());
		showDetailsScreen(aids_as_string);
		// exit because we'll be launched afresh when the next transaction occurs so no need to linger in the background
		if (transactionLaunch) {
			transactionLaunch = false;
			System.exit(0);
		}
	}

}

 Figure 11 - Handling a transaction

 

The key point to note in Figure 11 is that we check the value of a static boolean variable “transactionLaunch”. We set this variable to true when executing the code block related to entry point #3, with the argument “seTransactionListener”. This indicates that we are running in a new application instance, launched by the system. As such, once we’ve handled the transaction by passing details to the UI instance via the RuntimeStore, we can exit this instance by calling System.exit(0).

 

Let’s look at the showDetailsScreen method next:

 

private void showDetailsScreen(final String aids) {
  Backlight.enable(true,10);
  RuntimeStore store = RuntimeStore.getRuntimeStore();
  try {
    if (!Utilities.isUiRunning()) {
      // this launches the default entry point so our UI will be shown
      int pid = ApplicationManager.getApplicationManager().
                           launchApplication("NfcTransactionHandler");
    }
  } catch (final ApplicationManagerException e) {
    Utilities.log("XXXX  Error:" + e.getMessage());
  }
  store.put(PASSED_TO_UI_DATA_ID, aids);
}

 Figure 12 - passing transaction details to the UI

 

This method accomplishes a number of things:

  1. The back light is enabled to draw the user’s attention to the fact that something significant has occurred. Note that it is good practice to make a call to Backlight.enable(...) from within your main method when your application first runs in entry point #2. This is because use of this method is subject to application permissions and therefore, the first time it is called, the user will be required to grant that permission. You don’t want this dialogue to get in the way of an NFC payment transaction.
  2. In Utilities. isUiRunning(), we check the RuntimeStore for the presence of our Constants.UI_IS_RUNNING token, which tells us whether the UI instance is already running or not. If it is not running, we launch it using the ApplicationManager.
  3. We pass the AIDs received to the UI instance via the RuntimeStore.

Communicating with an applet

There may be occasions when your BlackBerry application needs to communicate with an applet in a secure element. The API used to accomplish this is known as JSR-177. JSR-177 allows applications to establish a connection with an applet in a secure element and exchange ISO 7816-4 application protocol data units (APDUs) with it. Generally, the application will formulate request APDUs, send them to the applet and receive and process response APDUs which get returned from the applet.

 

By definition therefore, you need to have some knowledge of ISO 7816-4 to be able to implement this aspect of an NFC application. ISO 7816-4 is quite a large subject and the best way to get to grips with it is to read the specification. We’ll just give you a flavour of what JSR-177 looks like here.

 

The following code fragment establishes an APDUConnection with an applet identified by an AID that we specify. It then sends a proprietary ISO 7816-4 APDU to the selected applet. Note that the ISO standard allows you to “invent” your own APDUs like this. The target, “selected” applet must understand the APDU of course. The application receives the response and does something meaningful with it.

 

APDUConnection conn = null;
// ISO 7816-4 header decode
// CLA=80
// INS=01
// P1-P2=0000
byte[] command = { (byte) 0x80, (byte) 0x01, (byte) 0x00, (byte) 0x00 };
byte[] response = null;
my_aid = "a0.00.00.00.04.11.12.33.22.11"; // this is a fake AID invented for this article
connection_string = "apdu:0;target=" + my_aid;		
try {
  conn =(APDUConnection) Connector.open(connection_string);
  try {
    response = apduConn.exchangeAPDU(command);
    /// do something with the response
  } catch ( Exception e1 ){
  }
  conn.close();  
} catch ( Exception e2) {
}

 Figure 13 - Using JSR-177

 

Using JSR-177 during transaction processing

Version 7.0 of the BlackBerry APIs offers the TransactionListener interface which we explored earlier on in this article. As you saw, the only information provided when a call to the onTransactionDetected method is made, is the AID(s) of the applet(s) which gave rise to the transaction event being raised. Sometimes your application will need more information about the transaction, such as its value for example. In the 7.0 APIs, your only choice is to use JSR-177 to ask the relevant applet for the required information after receiving the onTransactionDetected call back. You’d do this broadly as shown above, by establishing an APDUConnection to the relevant applet and then exchanging suitable APDUs to obtain your information. What those APDUs are will depend on your requirements and how the applet has been designed.

 

There are a couple of important points to be aware of here. Firstly, version 7.1 of the APIs introduces a new interface called TransactionListenerWithParams. This interface has an onTransactionDetected method with the following signature:

 

void onTransactionDetected(byte[][] aids,
                           byte[][] parameters)

 Figure 14 - TransactionListenerWithParams interface

 

This interface is in line with the recommendations made by the GSM Association in their specification entitled “NFC Handset APIs and Requirements”. A specification which indicates the way in which a UICC resident applet would use this capability is ETSI TS 102 622 (section 11.2.2.4). As such, at version 7.1 of the APIs, transaction events can pass miscellaneous information, not just applet IDs to your application and the second important point which we’ll move on to discuss below should not necessarily apply since it’s less likely you will need to connect back to the applet that raised the transaction event to obtain further data.

 

The second important point is that to connect back to an applet during the handling of a transaction requires an APDUConnection to that applet. In terms of ISO 7816-4, opening a connection is accomplished by sending a SELECT command. Applets are sometimes programmed to allow themselves to have been selected only once and to disallow multiple concurrent selection requests. In our scenario, transaction processing will have involved the applet being initially selected by the reader and when our BlackBerry application receives its call back to indicate a transaction was handled by the applet; it is possible that the reader will still have the applet selected. The interaction between applet and reader and between applet and BlackBerry application are completely independent of one another. Hence, there exists the possibility of a race condition which either you must deal with in your BlackBerry application or which must be dealt with by the applet developer.

 

In the event that you do try to connect to an applet which is not capable of such “multiple selection”, and which is still selected by the reader, you’ll get an Exception as a consequence of the applet returning an error status.

 

However, dealing with this behaviour in your BlackBerry application is not hard. The reader is not likely to keep the applet selected for long so a simple solution is to implement a retry algorithm which sleeps for a short interval (e.g. 100ms) between attempts to select the applet (i.e. to establish the APDUConnection) and makes a maximum number of attempts before concluding that there really is something wrong.

 

Tracking NFC service status

The article up to this point has armed you with the knowledge required to approach the primary issues:

 

  1. How to enable card emulation and route protocols appropriately;
  2. How to receive and handle transaction events, and;
  3. How to “talk to” an applet in a secure element using JSR-177 and ISO 7816-4 APDUs.

Now we’ll turn our attention to the question of how to determine the state of the overall NFC service on the smartphone. By “NFC service”, we essentially mean whether NFC has been switched on or off by the user from the BlackBerry Manage Connections screen as shown in Figure 15.

 

nfc_service.png

 

Figure 15 - NFC in the Manage Connections screen

 

To track the status of the NFC service, we’re provided with the NFCStatusListener interface. It has a single method, onStatusChange and this receives an int argument which comprises a bit mask indicating various service states. Constants corresponding to individual bit mask values are defined in the NFCManager class.

 

In the sample application “NfcTransactionHandler”, we maintain a visual indication of the status of the NFC service and card emulation (CE) mode via a graphical LED style representation.

 

nfctransactionhandler_leds.png

Figure 16 - LEDs indicating NFC service and card emulation mode statuses in the sample app

 

The MyNfcStatusListener class implements the NfcStatusListener interface and uses it to maintain these UI indicators.

 

public void onStatusChange(int nfcServicesAvailable) {
  boolean nfc_status = (nfcServicesAvailable != NFCManager.NFC_NONE);
  boolean ce_status = true;
  try {
      // ce is an instance of the CardEmulation class which is part of the sample
      // application and not the BlackBerry APIs
      // it uses the SecureElement getTechnologyTypes method to determine what NFC mode
      // and routing is currently selected for the “battery on” state
      ce_status = ce.isCeEnabled(SecureElement.BATTERY_ON_MODE);
  } catch(NFCException e) {
  }
  // update the UI with the new NFC and Card Emulation states
  screen.nfcStateChanged(nfc_status, ce_status);
}

Figure 17 - NfcStatusListener implementation

 

In common with other listener classes, you must register it with the system after instantiating your NFCStatusListener. In this case we do so using the NFCManager class.

 

NFCManager.addNFCStatusListener(nfc_status_listener);

Figure 18 - Registering a NfcStatusListener object

 

In addition to tracking NFC service state, we can explicitly request information regarding its state. We can also ask the user if they would like to enable NFC. Note that we cannot enable NFC programmatically without involving the user.

 

The following code fragment shows how to establish whether or not the NFC service is enabled:

 

public boolean isNfcEnabled() throws NFCException {
  // checks that NFC is enabled and that the required NFC service is available
  int service_status = NFCManager.getInstance().getAvailableNFCServices();
  boolean nfc_ok = (service_status != NFCManager.NFC_NONE);
  return nfc_ok;
}

 Figure 19 - Checking the NFC service state

 

To ask the user to enable NFC, we use the enableNFCByPrompt() method of NFCManager.

 

public void promptToEnableNFC() throws NFCException {
  synchronized (UiApplication.getEventLock()) {
    NFCManager.getInstance().enableNFCByPrompt();
  }
}

 Figure 20 - Asking the user to enable NFC

 

The user will see a dialogue similar to the one shown below and opt to either enable NFC or cancel the operation.

 

enable_nfc.png

 Figure 21 - The dialogue produced by enableNFCByPrompt()

 

Testing

To test a card emulation application fully, you will need to be able to exercise the NFC contactless interface by some means. This means being able to communicate with the applet in your secure element over ISO 14443 using ISO 7816-4 APDUs. How you do this depends on the detail of your application and what facilities you have available to you.

 

A “must have” component in any smart card developer’s armoury of tools is a card reader. With a card reader which supports NFC plugged into a PC over USB, it is possible to use tools of various sorts to conduct an exchange of ISO 7816-4 APDUs with the applet in the secure element.

 

reader.png

 Figure 22 - A BlackBerry Bold 9900 on top of a contactless card reader

 

The tools that the authors use most frequently are GPShell and Python with the pyscard API from GemAlto. Both are free of charge.

 

GPShell is, as the name suggests, a shell which supports a simple scripting language whose commands are based around the Global Platform standard. The following example script sends an ISO 7816-4 SELECT command via the reader to a BlackBerry smartphone which was placed on top of the reader.

 

mwoolley@CI0000000938774 /cygdrive/c/GPShell-1.4.3
$ ./GPShell.exe scripts/gemalto_sim_select_1.txt
mode_201
enable_trace
establish_context
card_connect
select -AID 6E6663746573743031
Command --> 00A40400096E6663746573743031
Wrapped command --> 00A40400096E6663746573743031
Response <-- 43617264456D759000
card_disconnect
release_context

Figure 23 - An example GPShell script

 

You can find out more about GPShell at the project’s wiki at the sourceforge site:

 

http://sourceforge.net/apps/mediawiki/globalplatform/index.php?title=Main_Page

 

Python with psycard is particularly powerful and we’ll have more to say about it in the future. For now, you can read all about it at its sourceforge site:

 

http://pyscard.sourceforge.net/

 

Code Signing Requirements

BlackBerry developers are familiar with the code signing process which applies to BlackBerry applications in general. When working with NFC card emulation, there are some additional requirements however. Firstly there are two additional signing keys of which you will require one. They’re called NFCR and RESE. If you’re working with the secure element in a UICC then you need NFCR. If you’re working with the BlackBerry embedded secure element you need RESE.

 

There’s a further issue which may apply however. It’s possible for a secure element to contain an Access Control File (ACF). This is a mechanism which allows the secure element owner to control which applications are permitted to interact with which particular applets. As such, if an ACF is in use then application cod files must usually be subject to a new signing process. It’s this signing process which allows applications to be identified and applicable rules in an ACF to be enforced by the system.

 

In contrast to the usual RIM application signing process, where RIM issue the signing keys and their signing servers participate in the process, the ACF related signing process does not involve RIM other than in the provision of a tool which allows you to sign your cod file. The tool is called CodTool and it uses key pairs in a standard Java key store to sign your cod file. The key is provided by the secure element owner, a carrier in the case of a UICC-resident secure element and RIM for the embedded secure element.

 

CodTool, NFCR and RESE are available on application from RIM. Their availability is restricted and depends on certain business and technical criteria being met.

 

MIDlets

We strongly recommend you develop your NFC applications using the BlackBerry APIs and not develop a MIDlet. The reasons for this are well documented and the following video in the developer resource centre enumerates some of the key differences:

 

http://supportforums.blackberry.com/t5/Java-Development/Contrasting-MIDlets-and-BlackBerry-Java-Appl...

 

If you do decide to develop a J2ME MIDlet however, you need to be aware of the following issues:

  1. You must still implement TransactionListener to receive transaction events when your application is running.
  2. To allow your MIDlet to be launched and receive transactions when it is not already running however, you need to use the PushRegistry. Having registered with the PushRegistry your MIDlet will be launched if your MIDlet is not running when a transaction event from an associated applet is raised.
  3. Importantly, note that it is permissible to have both a TransactionListener and PushRegistry registration for the same applet AID concurrently.

Using the PushRegistry in this way is defined in JSR-257. The BlackBerry APIs do not support JSR-257; rather, we allow JSR-177 style connection entries in the PushRegistry instead. Here’s an example:

 

String CONNECTION_STRING = "apdu:0;target=4e.46.43.54.65.73.74.65.72.20.31.2e.30";

PushRegistry.registerConnection(CONNECTION_STRING, this.getClass().getName(), "*");

 Figure 24 - APDU Connection PushRegistry registration

 

To receive transaction details from the PushRegistry you have to call listConnections(true) which provides a list of connections for which there is input available for the current MIDlet suite. The startApp() method would be a good place to do this.

 

String[] availableConnections = PushRegistry.listConnections(true);
if(availableConnections.length > 0) {
  if(availableConnections != null && availableConnections.length > 0) {
    // format is: apdu:0;target=4e.46.43.54.65.73.74.65.72.20.31.2e.30
    int index = availableConnections[0].indexOf("target=");
    if(index > -1) {
       Utilities.log("XXXX got message from PushRegistry:" + availableConnections[0]);
       String aid = availableConnections[0].substring(index + 7);
       // handle appropriately
    }
  }
}

  Figure 25 - Receiving transaction details from the PushRegistry

 

The Sample Application

As mentioned at the beginning of this article, we’ve developed an application which illustrates most of the important points and techniques described in this article. It’s called NfcTransactionHandler and you can find the full source code and resources for the application in the GitHub Samples-For-Java repository here:

 

https://github.com/blackberry/Samples-for-Java/tree/master/NFC

 

Note that we've used the latest version of the TransactionListener interface in the sample app (we made a change to this API  after the initial 7.0 version was released) so you'll need the 7.1 eJDE plug-in to be able to build from source.

 

The application is designed to be used with a test SIM which includes an applet which when selected, raises a transaction event. The usual approach to using the application is to select the applet using GPShell and a contactless reader. When the applet is selected and raises the transaction event, this should cause a call to the application’s TransactionListener and this indicated by the applet’s AID being displayed on the UI.

If you don’t have the necessary facilities available to you then you will not be able to test the application but hopefully the source code will still be informative.

 

When you launch the application, you will see a screen with four large buttons, a couple of graphical LEDs and an area shown as a red dotted line, which will receive updates when a TransactionListener call back is received. There’s also a settings screen which can be selected from the menu on the main screen.

 

The main screen is shown below.

 

transhandler_main1.png

  Figure 26 - The sample app UI with card emulation currently disabled

 

The four buttons function as follows:

 

Button

Functionality

Switch Card Emulation Off|On

Toggles Card Emulation mode on or off. The CE LED graphic indicates the current state.

Clear

Clears the AID display area which is the dotted line at the foot of the screen. This area is used to display the AID of any applet which raises a transaction event and for which we’re registered. The Clear button resets this area.

Exchange ISO 7816-4 APDU

Attempts to open an APDUConnection with an applet in the secure element indicated in the Settings screen and sends a proprietary APDU to it. Unless you know you have a suitable applet in an accessible secure element, you should expect this operation to fail. The event log will contain information which you may find informative however.

Close

Closes the UI but leaves the application running in background. Select the Kill option from the main menu if you want to terminate the application.

 Figure 27 - The sample app buttons

 

The two LEDs indicate the status of the NFC service and of card emulation mode (“CE” here). Green means “ON”, grey means “OFF” and red means “error”.

 

The initial screen shot shows card emulation is currently off. Clicking the first button in the top left of the 4 x 4 grid, switches it on so that the CE LED becomes green. If you click it and this does not happen, extract the device event log and examine it for errors by the way.

 

transhandler_main2.png

 Figure 28 - The sample app with card emulation now enabled

 

With card emulation enabled, you can now click the “Exchange ISO 7816-4 APDU” button. This will result in an attempt being made to select a particular applet on the UICC (unless you changed the settings) and send an APDU to it. If this succeeds you’ll see the response from that exchange on the screen. If it does not, you will see an error message.

 

This button will probably not work for you unless you have a suitable test SIM with an applet on it which understands the proprietary ISO 7816-4 APDU used in the sample application. If it doesn’t work, the code should still be useful to you as an example.

 

transhandler_main3.png

 Figure 29 - The sample app displaying the response from the ISO 7816-4 test APDU


With the test applet used by the authors, we see the result shown above. The “9000” at the end is the status word from the APDU response and means “command executed OK”. The “0020” is the response data from the applet. 

 

It’s been mentioned that there are settings which can be changed. Select “Settings” from the menu and you will see the screen below. Some settings may not work for you, depending on what type of NFC reader you are working with and whether or not you have permission and signing keys to allow use of either of the secure elements.

 

transhandler_main5.png

Figure 30 - The sample app settings screen

 

The authors use a test applet which raises transaction events when it is selected via the ISO 14443 interface using a reader plugged into a PC and the GPShell tool. When a transaction is raised and triggers a call to the TransactionListener, the received AID is logged on the screen as shown next:

 

transhandler_main6.png

Figure 31 - The sample app displaying the AID indicating a transaction event from the applet with that AID  

 

The code is organised into packages as shown below:

 

java_packages.png

Figure 32 - Sample app Java package structure

 

The main application class, NfcTransactionHandler, implements TransactionListener. The other areas of primary interest with respect to NFC are the nfc.sample.nfctransaction.nfc and nfc.sample.nfctransaction.commands packages. There’s also a rather nice multi-state button UI control in the nfc.sample.nfctransaction.buttons package. Not strictly related to NFC of course!

 

Summary

Card emulation is a large topic, spanning NFC and smart code protocol stacks and specialised domain specific standards such as EMV. We hope that this article has given you an introduction to the subject and made key aspects which are the concern of the BlackBerry application developer clear.

 

BlackBerry APIs are documented here if you'd like to browse further: http://www.blackberry.com/developers/docs/7.0.0api/

 

Footnote

You might be wondering about the Utilities.log method and why log entries are prefixed with the string “XXXX “? This has nothing to do with NFC of course but it does have some relevance in a somewhat indirect way so we’ll explain it here.

 

NFC applications developers will test using real smartphones pretty much all of the time. Developers of other types of application will, in contrast, work heavily with the BlackBerry simulators. Debugging with real smartphones can be a little slow so the authors have an approach which they think works well and it’s reflected here in the code fragments and the full sample application “NfcTransactionHandler”.  

 

The Utilities class uses the BlackBerry EventLogger API to write to the device event log. You need to initialise it once by calling initLogging() and then call the log method whenever you want to write to the log:

 

public class Utilities {

	static final long MYAPP_ID = 0x8172320e10e61b12L;

	public static void initLogging() {
		EventLogger.register(MYAPP_ID, "NfcTransactionHandler", EventLogger.VIEWER_STRING);
	}

	public static void log(String log_msg) {
		System.out.println(log_msg);
		boolean ok = EventLogger.logEvent(MYAPP_ID, log_msg.getBytes(), EventLogger.INFORMATION);
	}
}

 Figure 33 - Logging methods

 

 

Note that your MYAPP_ID value must be unique. Generating it using the “string to long” function which appears when you select and then right click on a string value from within the eJDE is recommended.

 

We tend to use EventLogger.INFORMATION for our logging level. The EventLogger on the smartphone will by default be working at WARNING level so before running a test, you will need to set it to INFORMATION level. You do this by holding down ALT and then pressing the key sequence L G L G. Go into the Options menu and you can change the logging level to INFORMATION there.

 

So that’s the background. The time saving part comes when you actually use the event log data, The Cygwin bash emulator comes with an implementation of the Unix® grep command and, you’ve guessed it, this is where the “XXXX” string comes into play. In a Cygwin window, after running a test and with our smartphone connected to our PC via USB, the following commands will download the event log from the smartphone and filter out all except our own log entries:

 

javaloader -u eventlog > eventlog.txt
grep XXXX eventlog.txt > app_trace.txt

  Figure 34 - Extracting sample app messages from the log

 

Log entries from our application are now in the app_trace.txt file.

 

We’d suggest removing event logging of this sort before going into production. Use of BlackBerry RAPC pre-processor directives should make it easy to generate production builds which do not include the logging whilst retaining the ability to generate builds which include them for testing purposes.

 

Glossary of NFC Terms

  • AID – Applet ID
  • APDU - Application Protocol Data Unit. A message type which forms part of a protocol and which may be exchanged between peers as either a request or a response message. Applications on a BlackBerry smartphone may communicate with applets in an SE using the ISO7816-4 APDUs for example.
  • CLF - Contactless Front-end. Part of the NFC Controller. Communicates via RF with an NFC reader.
  • HCI - Hardware Controller Interface. Amongst other things, this component of the NFC system architecture redirects radio communication to appropriate SE.
  • ISO7816-4 - the specification which defines the protocol which allows applications to communicate with applets installed in an SE or smart card.
  • NDEF - NFC Data Exchange Format
  • NFC - Near Field Communications
  • PCD – Proximity Coupling Device (also known as “card reader”)
  • PICC – Proximity Integrated Circuit Card
  • SE - Secure Element. A hardware component which can host and act as an execution environment for small software applications known, in this context, as "applets".
  • SIM - Subscriber Identity Module. In 2G modules this used to be synonymous with the SIM *card* i.e. the small smart card inserted in the handset. In 3G networks, the SIM is a software module installed on the UICC.
  • SWP - Single Wire Protocol.
  • UICC - Universal Integrated Circuit Card - the smart card used in mobile terminals in GSM and UMTS networks
Contributors