FAQs & How-To

Devs: How to Add NFC Support in BlackBerry 10 App

blackberry-dev-alpha

Two users in the BlackBerry developer support forums have written up a nice tutorial on adding NFC to a BlackBerry 10 app. Here’s the tutorial, which can alternatively be found here:

Introduction

This article is part of a series intended to help developers wishing to exploit NFC in their BlackBerry® 10 applications. Readers of this article should have some pre-existing knowledge of the fundamental architecture of NFC systems and be familiar with C/C++, Qt® and Cascades™. This article builds on the “NFC Tool” application that we’ve been evolving as a sample application and you are expected to have read the earlier articles on NFC Tool so that the context of this article can be fully appreciated.

 

This article will explain how to use the BlackBerry 10 C++ native API to develop software, which can interact with an applet running in the Secure Element (SE) of the UICC in a BlackBerry 10 handset. We’ve released version 4.0 of NFC Tool in full in our GitHub® repository, details of which can be found at the end of this article.

 

In terms of the standard NFC “modes of operation”, this article is concerned with Card Emulation Mode.

 

You may find the article entitled “NFC Card Emulation Primer”, which was written for BlackBerry® 7 a useful reference since it covers generally applicable concepts as well as BlackBerry 7 Java APIs for card emulation.

 

See http://supportforums.blackberry.com/t5/Java-Development/NFC-Card-Emulation-Primer/ta-p/1596893

 

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 Secure Elements, APDUs and the UICC

 

So, what do we mean by this heading? If you haven’t come across these concepts before then, before diving into the details of the application itself, we need to explain some of the terminology. Let’s use a diagram of the overall setup of this sample application to establish this context.

 

Figure 1 shows the main components. There are three physical pieces:

• A BlackBerry 10 device containing a UICC with a Secure Element (SE)
• An NFC reader
• A PC to which the NFC reader is attached via USB and which is capable of running applications that can communicate with the reader and by extension BlackBerry 10 handset.

 

fig1_architecture.png

 

Figure 1 Relationship of all the components in this example

 

There are two use cases that we’re going to cover in this article which are highlighted in the diagram:

 

1. Communicate with an Applet in the Secure Element
2. Detect an NFC Transaction Event

 

Let’s look at these in turn.
Use Case 1: Communicate with an Applet in the Secure Element

 

NFC Tool has acquired a new function on its main menu screen to support this use case as shown in Figure 2. This option will allow us to send an Application Protocol Data Unit (APDU) to an applet that exists in the Secure Element in the UICC.

 

IMG_00000019_360.png

 

Figure 2 NFC Tool’s home screen


On selecting this option the application flow allows you to specify a number of parameters for the APDU that will be sent to the chosen applet in the  SE (more on this later); and to review the response returned from the applet on the application event log screen.

 

fig3_ui.png

 

Figure 3 NFC Tool V4 – Issue an APDU to UICC: user interface overview
It’s as simple as that!

 

Use Case 2: Detect an NFC Transaction Event

 

In this case an external application on a PC is used to communicate with an applet in the Secure Element of the UICC. In a real-life example this would correspond to touching the handset to an external reader to perform, say, a payment operation in Card Emulation mode. The application in the PC communicates directly with the applet in the UICC‘s SE with no involvement of any application on the BlackBerry 10 handset itself.

 

In practical terms the setup looks something like the image in Figure 4 below.

 

fig4_reader.png

 

Figure 4 — Typical setup for the second use-case
However, the completion of this transaction may be of interest to an application in the handset and it’s possible to have the applet in the SE notify the handset that a transaction has occurred so that it may take some other action of its own.

 

fig5_tl.png

Figure 5 NFC Tool V4 – NFC Transaction Event: user interface overview

 

In the case of NFC Tool all we do is to display a dialog box showing the details of the event that has been notified by the SE as shown in Figure 4.
A Closer look at the Secure Element itself

 

A Secure Element is basically a secure container within which applications called applets can be run. Many applets can be installed in an SE and they are uniquely identified by an Application Identifier (AID) which is typically a long hexadecimal number. Typical examples of AIDs might be:

 

  • A000000018308005006563686F00 – this is the AID of a simple applet in the particular UICC that NFC Tool was developed against that simply echoes the contents of an APDU sent to it back to the initiator.

 

  • 6E6663746573743031 – this is the AID of a simple applet in the particular UICC that NFC Tool was developed against that will generate an EVT_TRANSACTION HCI event ( the proper term for the blue dashed line in Figure 1)

 

NOTE: It’s important to recognise that the behaviour of NFC Tool in these two use cases depends on having a UICC in the handset with an SE that contains two applets with the above AIDs that behave in the way described. How applets are written and installed in an SE like this is out of scope of this article. You may have access to UICCs that contain applets that behave in a similar way that you may be able to use but you would need to ensure that the AIDs of these applets are used in NFC Tool rather than the ones above.
If you examine the screenshot shown below in Figure 5 you’ll see that there are a number of fields that should have values. All the fields have default values but you should understand the meaning of these fields. Let’s look at them in turn.

fig6_apdu_form.png

 

Figure 6 Details of the APDU Screen

 

AID – this identifies the AID of the applet in the UICC’s SE to which we wish to send a command. The default value is that of the applet that will simply echo the command back to us as mentioned above.

 

NOTE: Unless you have access to this precise applet/AID on your own UICC you will have to replace that with the AID of an applet to which you have access.

 

CLA (Class) – this contains various flags that control the interpretation of the subsequent instruction (INS) itself. For example, it can identify the INS as a proprietary one rather than one of the standard ones defined in the ISO 7816-4 specification.

 

INS (Instruction) – this contains the specific operation that is to be performed by the card. Examples might be “READ”, “SELECT”, etc. In this case, by default, NFC Tool uses instruction 0×41 and this will be interpreted by the applet we’re using as a directive to echo the command back as a response.

 

Parameters P1 and P2 – these would carry any additional qualification information specific to the instruction (INS). In this example they are not used by the applet we’re using and they have been set to arbitrary values of 0×11 and 0×22 respectively.

 

Lc (Command Length) – if the command carries optional data L(c) would indicate the length if the data. L(c) may be absent if there is no data to be carried by the command. In this example there is no command data and this parameter is omitted.

 

Command data – if the command carries optional additional data they would be specified here. The default is to specific no additional data.

 

Le (Length expected) – if present this identifies the upper bound on the length of the expected response. In this example it’s been omitted.
You really need to read the ISO 7816-4 specification if you want to understand how to encode all the permutations of length and data fields.

 

Let’s look at response that may be returned from the applet. A response is really very simple. It consists of:

 

An optional Response Data field — this represents any data that the command expects to be returned.

 

Two Status Word (SW1 and SW2) fields – these are always present and reflect information that indicates the success or failure of the original command. The standard identifies the particular (SW1, SW2) response of (0×90, 0×00) as indicating SUCCESS.
If all went well then the response that might be seen in the application event log could look something like that shown in Figure 6. The main point to note is that this applet has responded successfully (the last two bytes in the response of “81411122222009000” are 0×9000 which indicates success) and the response payload contains some of the content of the original command since this is what our test “echo” applet does.

 

fig7_event_log.png

Figure 7 Successful Response to a command sent to the SE
On the other hand you might see the response shown in Figure 7. This means that there was no UICC present in the handset yet you tried to issue an APDU command to it; or that the SIM that you placed in the handset had no Secure Element inside it.

 

fig8_event_log.png

Figure 8 Missing UICC or no SE response
Right, that’s enough of the background and a description of the technology used by these use cases. Let’s see how this was all actually coded.

 

We’re interested in the core aspects of how to communicate with an applet in the SE and how to receive transaction events so we’ll not dwell on any of the UI aspects of the application or how it’s organised since we’ve covered this in previous articles and the pattern used in NFC Tool is well understood.

 

Implementation Details

In this section, we’ll review the changes that were made to NFC Tool to incorporate the features described in this article.

 

Implementation Details – Communicating with an Applet in the SE

 

Let’s look at the signature of the routine that is called when the user requests to “Issue the APDU” from the application APDU screen. “doIso7816Test()” is implemented as a Qt SLOT like the other similar routines within NfcWorker. The arguments are all derived from the data provided by the user on the screen.

 

void NfcWorker::doIso7816Test(const QVariant &aid, const QVariant &hex_cla, const QVariant &hex_ins, const QVariant &hexp1p2, const QVariant &hex_lc, const QVariant,&hex_command, const QVariant &hex_le) { …

 

Following the same pattern for NFC Tool all messages are written to the application event log using the “message()” signal. We’ll skip over most such messages in the code below for the sake of clarity unless it’s important to illustrate a point or handle a specific error condition.

 

Being QVariants we need to convert them to strings and build up the request APDU (“apdu”) as a string of hex characters in the first instance.

 

… emit message(QString(“ISO7816-4 test starts”)); QString _aid = aid.toString(); QString _hex_cla = hex_cla.toString(); QString _hex_ins = hex_ins.toString(); QString _hex_p1p2 = hexp1p2.toString(); QString _hex_lc = hex_lc.toString(); QString _hex_command = hex_command.toString(); QString _hex_le = hex_le.toString(); QString apdu = _hex_cla; apdu.append(_hex_ins); apdu.append(_hex_p1p2); apdu.append(_hex_lc); apdu.append(_hex_command); apdu.append(_hex_le); …

 

Now, we need to understand something about how Secure Elements in a device are addressed.

 

uiccSeReaderID – this is a unique handle to the “reader” that represents a Secure Element on the UICC. In principle there can be multiple SEs on a device and each is identified by its reader Id.

 

hSESession – Once you’ve located the reader representing the SE that you’re interested in you open a session to that SE.
seChannel – Once you’ve obtained a session with the SE you then open a logical channel to the applet on the SE that you’re interested in communicating with.

 

… // variables for handles uint32_t hSESession; uint32_t seChannel; uint32_t uiccSeReaderID; …

 We also need some variables to support the mechanics of locating readers, opening sessions and logical channels. You’ll see these used in the code that follows.

 

… // variables for retrieving the Readers, holders of possible SEs nfc_result_t rc; uint32_t numberOfReaders = 0; uint32_t *phReaders = NULL; static int DEF_LEN = 10; char readerName[DEF_LEN]; uint32_t len = 10; //variables for opening and exchanging data fcp_type_t fcpResponseType; int32_t openResponseLen; uint32_t exchangeResponseLen; uint32_t nReceiveAPDUBufferSize; uint8_t* result; …

The APIs used for SE / applet interaction mostly use byte arrays, “char *”, or “uint8_t *” types when passing data. Since the AID and APDU are currently in QString form they need to be converted to “uint_t *”. We then have the AID and the APDU in a form that can be used directly with the NFS SE APIs.

 

… QByteArray hex_encoded = QByteArray(aid.toByteArray()); int aid_size = _aid.length() / 2; uint8_t the_aid[aid_size]; int apdu_size = apdu.length() / 2; uint8_t the_apdu[apdu_size]; Utilities::hexToIntArray(_aid,the_aid); Utilities::hexToIntArray(apdu,the_apdu); …

The next thing we do is locate the reader that represents the UICC Secure Element. It’s necessary to iterate through all the available readers in the system to locate the one that we’re after. It’s identified by a reader name of “SIM”. The CHECK() macro defined in the project is just a convenience that checks return codes.

 

Notice the use of “malloc()” for dynamic space for the readers table and the corresponding “free()” at the end to balance the books!

 

The net result of this section is that we have identified the UICC reader and obtained its ID in “uiccSeReaderID”.

 

… uint32_t i; CHECK(nfc_se_service_get_num_readers(&numberOfReaders)); // Allocate space for the readers phReaders = (uint32_t*) malloc(sizeof(uint32_t) * numberOfReaders); // get the handles for the readers CHECK(nfc_se_service_get_readers(phReaders, &numberOfReaders)); // Iterate through the readers to find the SIM reader. int sim_readers_found=0; for (i = 0; i < numberOfReaders; i++) { len = 10; CHECK(nfc_se_reader_get_name(phReaders, readerName, &len)); if ((len == 3) && (strcmp(readerName, “SIM”) == 0)) { uiccSeReaderID = phReaders; sim_readers_found++; break; } } if (sim_readers_found == 0) { return; } // Deallocate the array for holding the readers. free(phReaders); …

Having located the UICC SE and obtained its ID we open a session to it which we can hold on to for the lifetime of the application should we want to open further connections to other applets.

 

It’s worth noticing the check that is performed here. Even though we may have successfully located the reader representing the UICC there may not actually be a SIM/UICC in it. Or, there may be a SIM but it may be a one that doesn’t have a Secure Element inside it! Yes, there are indeed such SIMs and it’s worth making this test.

 

… rc = nfc_se_reader_open_session( uiccSeReaderID, &hSESession ); if (rc != NFC_RESULT_SUCCESS) { emit message(QString(“ERROR opening session:%1″).arg(rc)); if (rc == NFC_RESULT_SE_NOT_PRESENT) { emit message(QString( “……or SIM does not include secure element”)); emit message(QString(“No SIM/UICC present”)); } return; } …

Now that we’ve successfully opened a session to the UICC reader the next step is to use that session to open a logical channel to the applet in the Secure Element in the UICC with which we wish to communicate. The applet is identified by its AID and in return we’ll obtain a logical channel handle in “seChannel”.

 

… fcpResponseType = OPEN_NO_FCP_INFO; openResponseLen = 0; rc = nfc_se_session_open_logical_channel(hSESession, the_aid, 12, fcpResponseType, &seChannel, &openResponseLen); if (rc != NFC_RESULT_SUCCESS) { emit message(QString(“ERROR opening logical channel:%1″).arg(rc)); return; } …

Finally we’ve got to the point where it’s possible to issue an APDU to the applet in the Secure Element in the UICC. The APDU has already been constructed and it’s only necessary to use the logical channel handle to do this.

 

The APDU is transmitted to the applet in the SE using “nfc_se_channel_transmit_apdu()”. The return code from this tells us whether the operation was successful or not. If it was successful we want to check what the response from the applet itself was.

 

As a side effect “nfc_se_channel_transmit_apdu()” lets us know what the length of the response is from the applet – it’s stored in “exchangeResponseLen” and the next task is to retrieve that information. Knowing the length we allocate (“malloc()”) a buffer to contain the response: “result”.

 

Recall that an APDU response will have the two status word bytes (SW1, SW2) representing the status of the request as set by the applet. If the buffer we’ve been returned is of length less that 2 then there is something wrong and it’s not possible to interpret the status.

 

Otherwise the response data is copied into the buffer we’ve just allocated using “nfc_se_channel_get_transmit_data()” and in this case the response is just logged in the application’s event log. In either case we need to free() the malloc()’d buffer to keep the books balanced.

 

… rc = nfc_se_channel_transmit_apdu( seChannel, the_apdu, apdu_size, &exchangeResponseLen ); if (rc != NFC_RESULT_SUCCESS) { emit message(QString(“ERROR transmitting APDU:%1″).arg(rc)); } result = (uint8_t*) malloc(sizeof(uint8_t) * exchangeResponseLen); nReceiveAPDUBufferSize = exchangeResponseLen; if (exchangeResponseLen >= 2) { CHECK(nfc_se_channel_get_transmit_data(seChannel, &result[0], &nReceiveAPDUBufferSize)); emit message( QString(“got response APDU. Len=%1″) .arg(nReceiveAPDUBufferSize)); QByteArray responseData = ByteArray::fromRawData(reinterpret_cast<const char *>(result), nReceiveAPDUBufferSize); QString responseAsHex = QString::fromAscii(responseData.toHex()); emit message(QString(“APDU response: %1″).arg(responseAsHex)); } free(result); …

Finally we tidy up and close the logical channel to the applet.

 

… if (NFC_RESULT_SUCCESS != nfc_se_channel_close_channel(seChannel)) { emit message(QString(“nfc_se_channel_close_channel failed”)); } }

Implementation Details – Registering to Receive Transaction Notification Events

 

Once more the Invocation Framework comes to our aid (pun intended!) here. We’ve already seen how we can register interest in the presentation of NFC NDEF Tags of different flavours. Figure 9 shows how to register to receive transaction notification events.

 

… <invoke-target id=”com.example.NfcTool.tl”> <entry-point>1</entry-point> <type>APPLICATION</type> <filter> <action>bb.action.NOTIFY</action> <mime-type>application/vnd.bb.nfc_transaction</mime-type> <property var=”uris” value=”aid://SIM/6e.66.63.74.65.73.74.30.31/”/> </filter> </invoke-target> …

Figure 9 Registering for Transaction Notification

 

Let’s look at this in a bit more detail.

 

1. Every “<invoke-target …>” stanza needs to be identified uniquely, so, we choose to continue to use the reverse DNS domain name pattern and extend it with a sub-domain “com.example.NfcTool.t1″.

 

2. Transaction notifications are always invoked using an action of “bb.action.NOTIFY” and a MIME type of “application/vnd.bb.nfc_transaction”.

 

    • The “uris” property further qualifies the registration by specifying the URI or URIs of the events we’re interesting in receiving; specifically this is where we identify the AID, or AIDs, of the applets we’re interested in and the SE where they are located.
    • The format of the URI is:

aid://<SE-type>/<AID>/

 

so, in this case you can see that an SE-Type of “SIM” is used to identify the UICC (remember we tested the reader name against the string “SIM” in the first use case).

 

    • Similarly, the AID we’re interested in is “6e.66.63.74.65.73.74.30.31″ which, if you recall was the one described in the section “A Closer look at the Secure Element itself“. This parameter is case sensitive and must be specified in lower case in exactly the format shown.
    • NOTE: Unless you have access to this precise applet/AID on your own UICC you will have to replace that with the AID of an applet to which you have access.

3. It’s worth pointing out that when an application is sent a transaction notification, it will be invoked in the background. From the background, the application may launch dialogs or toasts, but if a more complicated user experience is required then the application may bring itself to the foreground.

 

4. It’s also worth pointing out that, in order to receive a transaction notification for a given transaction an application must pass an ACF (Access Control Framework) check for all of the AIDs involved in the transaction. Discussion of ACF, though, is out of scope for this article, but suffice to say the test UICC and applet we’ve used to test NFC Tool has not imposed any ACF constraints.

 

The Invoke Manager pattern should be familiar from previous articles in this series and, as usual, the first step is to obtain a reference to the Invoke Manager and connect its “invoked()” SIGNAL to a method in our own class as shown in Figure 10.

 

… _invokeManager = new bb::system::InvokeManager(); … QObject::connect(_invokeManager, SIGNAL(invoked(const bb::system::InvokeRequest&)), this, SLOT(receivedInvokeRequest(const bb::system::InvokeRequest&))); …

 Figure 10 Connect our application with Invoke Manager

 

Now, whenever an NFC Transaction event occurs in the AID “6e.66.63.74.65.73.74.30.31” in the UICC then we’ll be called by the Invocation Framework at “receivedInvokeRequest()”.

 

Now, let’s take a step back and think what we want to do when we’re notified of a transaction. Remember that we’ll be invoked in the background so let’s launch a dialogue to tell the user what has happened. Figure 11 shows the mechanics of this.

 

… _systemDialog = new bb::system::SystemDialog(this); _systemDialog->setTitle(“NFC Transaction”); bb::system::SystemUiButton *confirmButton = _systemDialog->confirmButton(); confirmButton->setLabel(“OK”); connect(_systemDialog, SIGNAL(accepted()), this, SLOT(onDialogAccepted())); … } … void MainMenu::onDialogAccepted() { qDebug() << “XXXX MainMenu:onDialogAccepted()”; }

Figure 11 Setting up a dialogue

 

Firstly we obtain a reference to a “SystemDialog” instance and start configuring it. We add a title, a confirmation button labelled “OK”, and finally connect the SIGNAL from the confirmation button to a method in our own class where the event is just logged for the moment.

Now that we have the plumbing all set up let’s look (Figure 12) at what we have to do when a transaction event is received.

 

void MainMenu::receivedInvokeRequest(const bb::system::InvokeRequest& request) { QByteArray data = request.data(); if (request.mimeType().compare(“application/vnd.bb.nfc_transaction”) == 0) { QString json = QString(data); _systemDialog->setBody(json); _systemDialog->show(); } }

 Figure 12 Processing a Transaction Event

 

It’s deceptively simple isn’t it? The first thing we do is check that the invocation request is one that represents an NFC Transaction event. If it is, then we extract the data from the request, which is in the form of a JSON string, and pop up a dialogue box to the user with the JSON data as its content.

 

Triggering a Transaction Notification Event

 

To trigger an NFC Transaction event you need to write an application that performs a transaction on the applet. Or, you could make use of a tool called GPShell. GPShell is a tool that can be downloaded from SourceForge (http://sourceforge.net/projects/globalplatform/files/) and is commonly used to perform operations on smart cards that conform to the Global Platform set of standards. In this simple example we can use it to send a simple transaction to the BlackBerry device and examine the response just like in Figure 13.

 

fig13_gpshell.png

Figure 13 Using GPShell to initiate a Transaction Event

 

The AID we’re using (“6E6663746573743031″) in the UICC for this example will generate an EVT_TRANSACTION HCI event (the proper name for the NFC Transaction Event) when the card is disconnected after its initial selection by the reader.

Putting it Together

 

Figure 14 shows the contents of the dialogue box that is popped up on the handset as a result. Most of the data is understandable; the AID, the type of SE etc. But what’s this “eventData” field with a value of “YWJjZG=”?
Well, a quick check of the reference data for the AID that we’re using indicates that the applet will send a default message on the transaction event and that this message will be the string “abcde”. If we Base64 encode this string we get an encode result: “YWJjZG=”. This matches the field in the dialogue box exactly demonstrating that the message from the applet in the UICC has been correctly communicated to our application and that in conversion to JSON format Base64 encoding has been used since the message could be an arbitrary byte array rather than a string.

 

fig14_json.png

Figure 14 Contents of the NFC Transaction Event

Summary

We hope that this article and code sample has demonstrated how easy it is to use the BlackBerry 10 APIs in a C/C++ Cascades application to communicate with applets in a Secure Element and to be notified when transactions take place on the applet.

You can download NFC Tool V4, including its full source code from:

https://github.com/blackberry/Cascades-Community-Samples

 

The NFC Tool as written for the BlackBerry 10 “Dev Alpha” device and requires the following versions of the NDK and device software to build and run:

  • BlackBerry® 10 Native SDK 10.0.9
  • BlackBerry Dev Alpha Device Software 10.0.9 (Beta 3)

 

You can find details of other NFC related articles and sample applications written by Martin and John at
http://supportforums.blackberry.com/t5/Java-Development/NFC-Article-and-Code-Index/ta-p/1538775

You can contact Martin or John either through the BlackBerry support forums or through Twitter®:

 

 

Support Forum ID Twitter
Martin mwoolley @mdwrim
John jomurray @jcmrim







Leave a Reply