HostApduService
declares processCommandApdu()
method that the developer needs to implement. The method processCommandApdu()
is called when the service receives an Application Protocol Data Unit (APDU) sent by contactless/NFC reader. The developer needs to implement how to process APDUs specific to the card application(s) the service supports. The implementation can become complex if the service supports multiple card applications.SimplyTapp SDK provides a robust architecture where each card application is implemented in a "card agent". Using SimplyTapp SDK, there is no need for the developer to implement a complex
processCommandApdu()
method for a service that supports multiple card applications. Instead the developer implements process()
method in the card agent for each card application. A mobile application can support multiple card agents and card agents can be remotely deployed to the mobile application, similar to remotely deploying Java Card applet (aka cardlet) to the Secure Element. Essentially SimplyTapp SDK provides an architecture that is familiar to Java Card developers.I will describe how the card agent processes different APDU cases as defined in ISO/IEC 7816-4 specification.
ISO 7816-4 Case 1 | No Lc No Le Example: 80100000 |
ISO 7816-4 Case 2 | No Lc 1-byte Le (1 to 256, Le=0x00 represents 256) Example: 8012000000 |
ISO 7816-4 Case 3 | 1-byte Lc (1 to 255) No Le Example: 80140000081112131415161718 |
ISO 7816-4 Case 4 | 1-byte Lc (1 to 255) 1-byte Le (1 to 256, Le=0x00 represents 256) Example: 8016000008212223242526272800 |
Here is sample code for card agent implementation that demonstrates how to process the example APDUs. The class extends
com.simplytapp.virtualcard.Agent
. import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import com.simplytapp.virtualcard.Agent;
public class CardAgent extends Agent {
public void process(APDU apdu) throws ISOException {
byte[] apduBuffer = apdu.getBuffer();
byte claByte = apduBuffer[ISO7816.OFFSET_CLA];
byte insByte = apduBuffer[ISO7816.OFFSET_INS];
if (claByte == (byte) 0x80) {
if (insByte == (byte) 0x10) {
// Process case 1 command APDU.
processCase1Apdu();
// Return SW=0x9000.
}
else if (insByte == (byte) 0x12) {
// Process case 2 command APDU.
// Copy response data to APDU buffer.
System.arraycopy(responseData, 0,
apduBuffer, 0, responseData.length);
short le = apdu.setOutgoing();
if (responseData.length > le) {
le = (short) responseData.length;
}
apdu.setOutgoingLength(le);
apdu.sendBytes((short) 0, le);
// Return response data with SW=0x9000.
}
else if (insByte == (byte) 0x14) {
// Process case 3 command APDU.
short lc = apdu.setIncomingAndReceive();
// Save command data from APDU buffer.
System.arraycopy(apduBuffer, ISO7816.OFFSET_CDATA,
commandData, 0, lc);
// Return SW=0x9000.
}
else if (insByte == (byte) 0x16) {
// Process case 4 command APDU.
short lc = apdu.setIncomingAndReceive();
// Save command data from APDU buffer.
System.arraycopy(apduBuffer, ISO7816.OFFSET_CDATA,
commandData, 0, lc);
// Copy response data to APDU buffer.
System.arraycopy(responseData, 0,
apduBuffer, 0, responseData.length);
short le = apdu.setOutgoing();
if (responseData.length > le) {
le = (short) responseData.length;
}
apdu.setOutgoingLength(le);
apdu.sendBytes((short) 0, le);
// Return response data with SW=0x9000.
}
}
}
}
The card agent can also process extended length APDUs as defined in ISO/IEC 7816-4 specification. The maximum supported length using extended length is 32767 to be consistent with Java Card API.
ISO 7816-4 Case 1 | Not Applicable |
ISO 7816-4 Case 2 | No Lc 3-byte Le (1 to 32767, Le=0x000000 represents 32767) Example: 80120000000000 |
ISO 7816-4 Case 3 | 3-byte Lc (1 to 32767) No Le Example: 801400000000081112131415161718 |
ISO 7816-4 Case 4 | 3-byte Lc (1 to 32767) 2-byte Le (1 to 32767, Le=0x0000 represents 32767) Example: 8016000000000821222324252627280000 |
Here is sample code for card agent implementation that demonstrates how to process the example extended length APDUs. The class extends
com.simplytapp.virtualcard.Agent
and implements javacardx.apdu.ExtendedLength
. import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacardx.apdu.ExtendedLength;
import com.simplytapp.virtualcard.Agent;
public class CardAgent extends Agent implements ExtendedLength {
public void process(APDU apdu) throws ISOException {
byte[] apduBuffer = apdu.getBuffer();
byte claByte = apduBuffer[ISO7816.OFFSET_CLA];
byte insByte = apduBuffer[ISO7816.OFFSET_INS];
if (claByte == (byte) 0x80) {
if (insByte == (byte) 0x12) {
// Process case 2 command APDU.
// Copy response data to APDU buffer.
System.arraycopy(responseData, 0,
apduBuffer, 0, responseData.length);
short le = apdu.setOutgoing();
if (responseData.length > le) {
le = (short) responseData.length;
}
apdu.setOutgoingLength(le);
apdu.sendBytes((short) 0, le);
// Return response data with SW=0x9000.
}
else if (insByte == (byte) 0x14) {
// Process case 3 command APDU.
short receivedLen = apdu.setIncomingAndReceive();
// Save command data from APDU buffer.
System.arraycopy(apduBuffer, apdu.getOffsetCdata(),
commandData, 0, receivedLen);
short lc = apdu.getIncomingLength();
// Check if additional command data not yet received.
if (receivedLen != lc) {
short commandDataOffset = receivedLen;
// Receive more command data until no more available.
receivedLen = apdu.receiveBytes((short) 0);
while (receivedLen != 0) {
// Save additional command data from APDU buffer.
System.arraycopy(apduBuffer, 0,
commandData, commandDataOffset, receivedLen);
commandDataOffset += receivedLen;
receivedLen = apdu.receiveBytes((short) 0);
}
}
// Return SW=0x9000.
}
else if (insByte == (byte) 0x16) {
// Process case 4 command APDU.
short receivedLen = apdu.setIncomingAndReceive();
// Save command data from APDU buffer.
System.arraycopy(apduBuffer, apdu.getOffsetCdata(),
commandData, 0, receivedLen);
short lc = apdu.getIncomingLength();
// Check if additional command data not yet received.
if (receivedLen != lc) {
short commandDataOffset = receivedLen;
// Receive more command data until no more available.
receivedLen = apdu.receiveBytes((short) 0);
while (receivedLen != 0) {
// Save additional command data from APDU buffer.
System.arraycopy(apduBuffer, 0,
commandData, commandDataOffset, receivedLen);
commandDataOffset += receivedLen;
receivedLen = apdu.receiveBytes((short) 0);
}
}
// Copy response data to APDU buffer.
System.arraycopy(responseData, 0,
apduBuffer, 0, responseData.length);
short le = apdu.setOutgoing();
if (responseData.length > le) {
le = (short) responseData.length;
}
apdu.setOutgoingLength(le);
apdu.sendBytes((short) 0, le);
// Return response data with SW=0x9000.
}
}
}
}
Hi Ming, thanks for the article explaining about card agents. I have created an app which loads card from the SimplyTapp server as given here http://blog.simplytapp.com/2014/10/the-absolute-simplest-hce-application.html . Now I want to read card details such as Ppse, Card Aid, Processing options, Swipe data from VirtualCard object loaded from the server. Can you please help me how I can achieve this, I would be grateful for your help.
ReplyDeleteThanks,
Pradeep.
Great Article
Deleteblockchain projects for students
IEEE Projects for Engineering Students
JavaScript Training in Chennai
Networking Projects
JavaScript Training in Chennai
Hi Ming, thanks for the blog on HCE. I am using SimplyTapp sdk as given in http://blog.simplytapp.com/2014/10/the-absolute-simplest-hce-application.html . But am facing 2 issues, one is a crash whose stacktrace is given below
ReplyDeleteW/dalvikvm( 9324): threadid=17: thread exiting with uncaught exception (group=0x41efec08)
D/MainActivity( 9324): Account is Disabled cardId=6164 code=24
D/MainActivity( 9324): Account is Disabled cardId=6164 code=24
E/AndroidRuntime( 9324): FATAL EXCEPTION: Thread-2714
E/AndroidRuntime( 9324): Process: com.example.sampletapp, PID: 9324
E/AndroidRuntime( 9324): java.lang.NullPointerException
E/AndroidRuntime( 9324): at com.simplytapp.cardagent.c.run(SourceFile:1794)
E/AndroidRuntime( 9324): at java.lang.Thread.run(Thread.java:841)
W/ActivityManager( 3042): Force finishing activity com.example.sampletapp/.MainActivity
I/CardAgent( 9324): activated, tGetAccountParams is still accessing remote card applet, waiting...
I/ServiceKeeper( 3042): In getseinfo pid = 3042 uid = 1000 seinfo= system
D/CrashAnrDetector( 3042): processName: com.example.sampletapp
D/CrashAnrDetector( 3042): broadcastEvent : com.example.sampletapp data_app_crash
W/ApplicationPackageManager( 3042): getCSCPackageItemText()
V/SmartFaceService - 3rd party pause( 3042): onReceive [android.intent.action.ACTIVITY_STATE/com.example.sampletapp/pause]
D/SSRMv2:CustomFrequencyManagerService( 3042): acquireDVFSLockLocked : type : DVFS_MIN_LIMIT frequency : 1200000 uid : 1000 pid : 3042 pkgName : ACTIVITY_RESUME_BOOSTER@4
W/ActivityManager( 3042): mDVFSHelper.acquire()
In another issue, am trying you read card data using SoftPcd as below but transceiveWithCard() function is returning same value 6F00 in all the cases. Your help would be greatly appreciated.
SoftPcd softPcd = new SoftPcd((short)5000);
try {
virtualCard.transactWithSoftPcd(softPcd);
} catch (IOException e) {
e.printStackTrace();
}
try {
softPcd.connect();
byte[] apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xA4,0x04,0x00,0x05,(byte)0x32,0x50,0x41,0x59,(byte)0x2E});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xA4,0x04,0x00,0x07,(byte)0xA0,0x00,0x00,0x02,0x77,0x10,0x10,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{(byte)0x80,(byte)0xA8,0x00,0x00,0x15,(byte)0x83,0x13,(byte)0xD0,(byte)0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x01,0x24,0x01,0x24,0x02,0x66,0x33,(byte)0x82,0x01,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x01,0x0C,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x01,0x14,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x02,0x14,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x03,0x14,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x04,0x14,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{0x00,(byte)0xB2,0x01,0x1C,0x00});
apdu = softPcd.transceiveWithCard(new byte[]{(byte)0x80,(byte)0xAE,(byte)0x80,0x00,0x2A,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24,
0x00,(byte)0x80,0x00,(byte)0x80,0x00,0x01,0x24,0x13,0x06,0x27,0x00,0x02,0x66,0x33,(byte)0x82,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00});
softPcd.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
Thanks,
Pradeep.
I have read your blog its very attractive and impressive. I like it your blog.
ReplyDeleteJava Training in Chennai | Core Java Training in Chennai
Online Java Training | Java EE Training Institute in Chennai
Get this mobistealth app that would be a nice help for everyone obsessed with security.
ReplyDeleteThanks for the post, I am techno savvy. I believe you hit the nail right on the head. I am highly impressed with your blog. It is very nicely explained. Your article adds best knowledge to our Java Online Training from India. or learn thru Java Online Training from India Students.
ReplyDeleteThanks for the post, I am techno savvy. I believe you hit the nail right on the head. I am highly impressed with your blog. It is very nicely explained. Your article adds best knowledge to our Java Online Training from India. or learn thru Java Online Training from India Students.
ReplyDeleteCIITN is located in Prime location in Noida having best connectivity via all modes of public transport. CIITN offer both weekend and weekdays courses to facilitate Hadoop aspirants. Among all Hadoop Training Institute in Noida , CIITN's Big Data and Hadoop Certification course is designed to prepare you to match all required knowledge for real time job assignment in the Big Data world with top level companies. CIITN puts more focus in project based training and facilitated with Hadoop 2.7 with Cloud Lab—a cloud-based Hadoop environment lab setup for hands-on experience.
ReplyDeleteCIITNOIDA is the good choice for Big Data Hadoop Training in NOIDA in the final year. I have also completed my summer training from here. It provides high quality Hadoop training with Live projects. The best thing about CIITNOIDA is its experienced trainers and updated course content. They even provide you placement guidance and have their own development cell. You can attend their free demo class and then decide.
Hadoop Training in Noida
Big Data Hadoop Training in Noida
It is nice blog Thank you provide important information and i am searching for same information to save my time Big data hadoop online Training
ReplyDeleteappvn
hotmail sign up login
Thanks for this blog, I really enjoyed reading your post.
ReplyDeleteNorton Antivirus Customer Service Number
Norton Antivirus Customer Service Number
bitdefender helpline phone number
bitdefender tech support phone number
technical support for yahoo mail phone number
Thanks for sharing such a nice Blog.I like it.
ReplyDeletenorton.com/setup
mcafee.com/activate
Microsoft Edge Phone number
webroot activation
www trendmicro com bestbuypc
Thanks for sharing such a nice Blog.I like it.
ReplyDeletenorton.com/setup
norton com/setup
norton.com setup product key
install norton using product key
The card agent can also process extended length APDUs as defined in ISO/IEC 7816-4 specification. The maximum supported length using extended length is 32767 to be consistent with Java Card API. old gold earrings design , head pieces for races , jewelry boxes wholesale , faux fur scarf
ReplyDeleteCelebrity net worth is a website which reports estimates of the total assets and financial activities of celebrities. Read it for more information.
ReplyDeleteThank a lot. You have done excellent job. I enjoyed your blog . Nice efforts
ReplyDeleteCyber Security Course in Bangalore
Nice Blog and i would like to thank for the efforts you have made in writing this post, hoping the same best work from you in the future as well. Thanks for sharing. Great websites!
ReplyDeleteTableau Training in Bangalore
Such a very useful article and very interesting to read this article, i would like to thank you for the efforts you had made for writing this awesome article. Thank you!
ReplyDeletePython Training in Bangalore
I really want to appreciate the way to write this
ReplyDeleteomni-channel
ivrs
ip-pbx
Call Center Software
Call Center Solution
Call Center Solutions