Javacard.framework.APDU sendBytes method
In the class javacard.framework.APDU, I found that in several methods such as sendBytes(short bOff, short leng) or public void sendBytesLong(byte[] outData, short bOff, short len), they say:
"Requiring that the buffer not be altered allows the implementation to reduce protocol overhead by transmitting the last part of the response along with the status bytes."
I can not understand it so well. Why is it related to protocol overhead reduction? And what is "status bytes"?
Your reply, whether helpful or not, is highly appreciated
Jason
So you mean when it transmits the last packet including status bytes ~~> there would be one transmission only ~~> instead of two transmissions that last data is sent first and status bytes are sent then.
~~> thus, one (instead of two) can reduce the slight protocol overhead
When this process is repeated for each APDU response, it can lead to a multiple of slight overheads ~~> reduce the protocol overhead significantly
Is that right?
Jason
Similar Messages
-
Structure Or Record In JavaCard Framework
Can anybody please tell me if there is a way to define or implement records or structures in Javacard Framework??
My IDE is eclipse and I have so many master_detail data to store in Javacard, because my card does not support DB storage(SCQL) I'm searching a way better than storring data just in arrays...
any idea about better kind of storring data on card would be so much appreciated --<--@
my data are some thing like this:
Name,Family,Age,Sex,CreditNo,....
and also:
Master : DateOfVisit, TimeOfVisit, CodeOfVisit
Detail: IndexCode, DrugName, DrugInstruction
an Example is ::
Name:Hana
Family:Bijani
Age:25
Sex:Femail
CreditNo:176.3434
Data1
DateOfVisit:2009-08-08
TimeOfVisit:14:23
CodeOfVisit:123
IndexCode:1 DrugName:Drug A DrugInstruction: someinstructA
IndexCode:2 DrugName:Drug B DrugInstruction: someinstructB
Data2
DateOfVisit:2009-08-06
TimeOfVisit:14:23
CodeOfVisit:12345
IndexCode:1 DrugName:Drug A DrugInstruction: someinstructA
IndexCode:2 DrugName:Drug B DrugInstruction: someinstructB
IndexCode:3 DrugName:Drug C DrugInstruction: someinstructC
IndexCode:4 DrugName:Drug D DrugInstruction: someinstructD
Kind Regards
Hanawhat you want is really simple: it's a class:
public class record {
public byte[] name;
public short credit;
//no constructor means default void constructor
//use
class main {
private record[] records;
private short record_count;
//in a method, create a record
short rec_num = record_count++;
records[rec_num]=new record();
records[rec_num].credit = .....
records[rec_num].name=new byte[16];
JCSystem.arrayCopyNonAtomic( data..... , offset..... records[rec_num].name,16);
//Etc
cheat sheet:
- no string in javacards, use byte[] arrays, and encode strings to ASCII UTF8 or whatever
- no int except in rare cards, use shorts for 16 bits values, arrays of bytes to simulate ints
- no pointers in java
- struct are classes
- byte[] arrays created with new are non volatile
in general, cards are dumb. they only store raw byte arrays and the actual structure management is left to the host. This is a very robust and ubiquitous design, allowing reuse and simpification of on card code.
So in a perfect world you should'nt need a class to store records. A byte array is sufficient.
Imagine one day you want to add a new field in your record. argh!! you have to recompile/redeploy a new applet. If some millions clients already have it... fail!
However if you only store a raw record, it's just a matter or recompiling a basic java/whatever application, not a highly embedded code :) -
OCF or Javacard.Framework
OCF or Javacard.Framework? which one is better? I'm alittle confused with these concepts..
as I told in my last post my pc application is written in Delphi language and I installed my applet into card which delphi app send data to this applet via APDU..
now the question is Which one could be better to use in my applet? OCF or Javacard.Framework??
regardsFrom my understanding OCF is an off-card API for communicating with cards and readers with Java. The card you have should have the org.globalplatform package and won't have OCF. If you want your applet to be portable across different cards, you should probably stick with javacard.framework.
JCOP Tools should also help with this. It will only allow you to build against standard libraries. If you have vendor specific libraries for the target card you are using, you will need to get the Jar files to build against from them.
Cheers,
Shane -
I am working on R12.1.3 multi node shared appltop installtion on OEL 5.4. installations were successful and running fine since 10 days , today suddnly i have got the error stack on login screen. please help.
Error Page
Exception Details.
oracle.apps.fnd.framework.OAException: Illegal method call because there is no database connection.
at oracle.apps.fnd.framework.webui.OAPageErrorHandler.prepareException(OAPageErrorHandler.java:1251)
at oracle.apps.fnd.framework.webui.OAPageBean.preparePage(OAPageBean.java:2195)
at oracle.apps.fnd.framework.webui.OAPageBean.preparePage(OAPageBean.java:543)
at oracle.apps.fnd.framework.webui.OAPageBean.preparePage(OAPageBean.java:431)
at OA.jspService(_OA.java:212)
at com.orionserver.http.OrionHttpJspPage.service(OrionHttpJspPage.java:59)
at oracle.jsp.runtimev2.JspPageTable.service(JspPageTable.java:379)
at oracle.jsp.runtimev2.JspServlet.internalService(JspServlet.java:594)
at oracle.jsp.runtimev2.JspServlet.service(JspServlet.java:518)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:713)
at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:370)
at com.evermind.server.http.ServletRequestDispatcher.unprivileged_forward(ServletRequestDispatcher.java:259)
at com.evermind.server.http.ServletRequestDispatcher.access$100(ServletRequestDispatcher.java:51)
at com.evermind.server.http.ServletRequestDispatcher$2.oc4jRun(ServletRequestDispatcher.java:193)
at oracle.oc4j.security.OC4JSecurity.doPrivileged(OC4JSecurity.java:284)
at com.evermind.server.http.ServletRequestDispatcher.forward(ServletRequestDispatcher.java:198)
at com.evermind.server.http.EvermindPageContext.forward(EvermindPageContext.java:395)
at OA.jspService(_OA.java:221)
at com.orionserver.http.OrionHttpJspPage.service(OrionHttpJspPage.java:59)
at oracle.jsp.runtimev2.JspPageTable.service(JspPageTable.java:379)
at oracle.jsp.runtimev2.JspServlet.internalService(JspServlet.java:594)
at oracle.jsp.runtimev2.JspServlet.service(JspServlet.java:518)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:713)
at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:370)
at com.evermind.server.http.ServletRequestDispatcher.unprivileged_forward(ServletRequestDispatcher.java:259)
at com.evermind.server.http.ServletRequestDispatcher.access$100(ServletRequestDispatcher.java:51)
at com.evermind.server.http.ServletRequestDispatcher$2.oc4jRun(ServletRequestDispatcher.java:193)
at oracle.oc4j.security.OC4JSecurity.doPrivileged(OC4JSecurity.java:284)
at com.evermind.server.http.ServletRequestDispatcher.forward(ServletRequestDispatcher.java:198)
at com.evermind.server.http.EvermindPageContext.forward(EvermindPageContext.java:395)
at OA.jspService(_OA.java:221)
if any one got same issue pls help.
Thx
RBHussain,
No Errors found in Db alert log files.
same issue in all client systems.
only Apache service is showing as down in adopmnctl stattus
You are running adopmnctl.sh version 120.6.12010000.5
Checking status of OPMN managed processes...
--------------------------------------------------------------+---------
ias-component | process-type | pid | status
--------------------------------------------------------------+---------
OC4JGroup:default_group | OC4J:oafm | 3839 | Alive
OC4JGroup:default_group | OC4J:forms | 3770 | Alive
OC4JGroup:default_group | OC4J:oacore | 3623 | Alive
HTTP_Server | HTTP_Server | 1802 | Stop
Thx
RB -
Export file framework.exp of package javacard.framework not found
Hi,
trying to convert the HelloWord example of the Sun Javacard Kit (2.2.2), i get the "error: export file framework.exp of package javacard.framework not found". I have compiled the file according to the documentation and i am still following the documentation for converting it.
this is the command i use:
%JC_HOME%/bin/converter.bat -config C:\java_card_kit-2_2_2\samples\src\com\sun\javacard\samples\HelloWorld\HelloWorld.opt
Ideas?
Thanks
Edited by: uig on Oct 23, 2007 7:54 AMhow did you compile ur helloworld.opt file coz when i tried it i got this err msg
call %JC_HOME%\bin\converter -config ..\src\com\sun\javacard\samples\HelloWorld\HelloWorld.opt
and got this err
Exception in thread "main" java.lang.NoClassDefFoundError: Files\Java\jre1/6/0_03\lib\ext\QTJava/zip; -
There is not javacard.framework in Java Card 3.0.4
I tried to write a javacard applet. So,
Download Java Card Classic Development Kit 3.0.4 (java_card_kit-classic-3_0_4-rr-bin-do-b28-windows-06_sep_2011.jar) that I get its JAR File
I add the JAR File in to Eclipse by add it in the Java Build Path>Library.
But when I wanted to import javacard.framework, I got the "javacard.framework cannot be resolved" error. Moreover, when I saw inside the Development Kit, there was no javacard.framwork package in it. There is only "com.","net.","apache." package.I can execute it. Now, I can get all stuff including the javacardx.framework.
I download JCDE and and put it into Eclipse Folder. There is the "Java Card" Menu on the top bar of eclipse. I set the JavaCard home at the preference of the menu to My installed JavaCard Development kit folder but I cannot apply . Eclipse said there is not converter.jar in the folder. So, I have to set the JavaCard home to My JavaCard 2.2.1 folder instead.
However, Eclipse still give me the "javacard.framework cannot be resolved" error -
Generating token for javacard framework?
Hi,
I am implementing JCRE and it needs to support all APIs that are specified by Oracle JCRE.
It means that beside the coding/ implementation of each class and method, My framework needs to have tokens of each class, method and field as same as tokens of corresponding Oracle API classes, methods and fields.
I don't know if there is a special rule to set token for each framework related item? Or Tokens will be changed if there are changes in framework?
thanks,Stratos,
Thanks for your inputs,
I changed the code as you suggested , now my whole code looks like :
<%@ page import="com.crystaldecisions.sdk.framework.*" %>
<%@ page import="com.crystaldecisions.sdk.exception.SDKException" %>
<%@ page import="com.crystaldecisions.sdk.occa.security.*" %>
<%
boolean loginSuccessful = false;
IEnterpriseSession boEnterpriseSession = null;
String username = "user";
String password = "Password";
String cmsname = "Server";
String authenticationType = "secEnterprise";
try {
//Log in.
boEnterpriseSession = CrystalEnterprise.getSessionMgr().logon( username, password, cmsname, authenticationType);
if (boEnterpriseSession == null) {
out.print("<FONT COLOR=RED><B>Unable to login.</B></FONT>");
} else {
loginSuccessful = true;
} catch (SDKException sdkEx) {
out.print("<FONT COLOR=RED><B>ERROR ENCOUNTERED</B><BR>" + sdkEx + "</FONT>");
if (loginSuccessful) {
ILogonTokenMgr boLogonTokenMgr = boEnterpriseSession.getLogonTokenMgr();
String logonToken = boLogonTokenMgr.createLogonToken("", 60, 1);
//String logonToken = boLogonTokenMgr.getDefaultToken();
String infoViewURL = null;
String tokenParam = null;
String redirectURL = null;
infoViewURL = "http://Server:8080/InfoViewApp/logon.jsp";
tokenParam = "ivsLogonToken=" + logonToken;
redirectURL = infoViewURL + "&" + tokenParam;
pageContext.forward( "openDocument.jsp?iDocID=" + 4668 + "&token=" + tokenParam);
%>
But I am still getting the Infoview Login Page . The url on the login page is
http://server:8080/OpenDocument/opendoc/logonTrustedAuth.do?appKind=InfoView&iDocID=4668&isApplication=true&token=ivsLogonToken%server%3A6400%4021181JIipxt70VM0kd90v21179JFd4dHn7kW2FKSBi
We can see that a token is being generated and appended to this url but it is not passing the user name and password.
Please let me know what you think about this. -
Default Framework page Isolation method changed
We changed the Isolation method to URL instead of embedded on all of the iviews in the Default Framework page.
Now we cannot view the Portal Content Directory. Is there any method to fix this by going to a URL.
We tried - http://myServer:50000/irj/portal?NavigationTarget=ROLES://portal_content/administrator/content_admin/worksets/com.sap.portal.content_admin_ws/com.sap.portal.content_admin_wsExplorer and it did not work.
Thanks in advance,
D. MaupinHi,
You can resolve by using the steps below:
1. Create a transport package for the Default framework page in a system where the properties are correct . Export the epa file and save locally
2. Login to the Portal where the properties have been messed up.
3. On the same Browser window change the URL to
http://<server>:<port>/irj/servlet/prt/portal/prtroot/com.sap.portal.pcd.admintools.import.default
This should open the Import Transport application
4. Import the local transport .
5. Logout and login again to the portal.
Thanks
Prashant -
OIM ICF Connector Framework - Enable Disable Method
Hi ,
I am currently working on developing custom OIM connector using ICF Framework , I am trying to create an adapter for application user enable disable . I am not sure about which method gets called to disable the user .
Do I need to write a seperate disableUser Method in the connector code , currently have methods for Create , Update and delete , do I need to write 2 more methods for Enable Disable of users.
I belive th UpdateOP interface is called during the disable / enable process .
any help would be much appreciated.
Cheers
EaswaranI'm getting the same error when it runs update user to add child values:
Thread Id: 125 Time: 2013-02-22 09:24:53.204 Class: org.identityconnectors.framework.api.operations.UpdateApiOp Method: update Level: OK Message: Exception:
java.lang.NullPointerException: Parameter 'uid' must not be null.
This is the attribute map that get's passed in. unixids are the child values.
Thread Id: 125 Time: 2013-02-22 09:24:53.202 Class: org.identityconnectors.framework.api.operations.UpdateApiOp Method: update Level: OK Message: Enter: update(ObjectClass: __ACCOUNT__, null, [Attribute: {Name=unixuids, Value=[sdfasdfasd]}], null)
Here is my what my schema looks like for if it helps:
<ObjectClassInfos>
<ObjectClassInfo type='__ACCOUNT__' container='false' embedded='false'>
<AttributeInfos>
<AttributeInfo name='unixuids' type='String'>
<AttributeInfoFlag value='MULTIVALUED'/>
</AttributeInfo>
<AttributeInfo name='__NAME__' type='String'>
<AttributeInfoFlag value='REQUIRED'/>
<AttributeInfoFlag value='NOT_UPDATEABLE'/>
</AttributeInfo>
</AttributeInfos>
</ObjectClassInfo>
</ObjectClassInfos>
How did you fix your problem?
Edited by: DJ on Feb 22, 2013 9:58 AM -
Javacard.framework not found error
I am using this sws for my pc.
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)
I tried to compile the Wallet.java for test purposes. But when I use javac Wallet.java , no package found error is given. These package is coming default, as i read from a article. ?????Dear Friend,
What JDK you are using? Are you sure converter takes your OPT file?
Yours sincerely
Dmitri -
Use APDU instance in install method?
Hi
I want to use OPSystem.getCPLCData(javacard.framework.APDU apdu, short apdu_offset, short cplc_offset, short length) in install method.
but APDU is not accessible in install method.
like this,
public static void install(bytes[] bArray, short bOffset, byte bLength){
short apdu_offset = (short)0;
short cplc_offset = (short)8;
short length = (short)2;
OPSystem.getCPLCData(apdu, apdu_offset, cplc_offset length);
what should I do to solve this?
Thanks in advance
rabiiirabiii wrote:
Hi
I want to use OPSystem.getCPLCData(javacard.framework.APDU apdu, short apdu_offset, short cplc_offset, short length) in install method.
but APDU is not accessible in install method.That is because the byte[] in the install method is the global buffer that is in the APDU class. You will need to defer this call until the process method has been invoked.
Cheers,
Shane -
[Javacard] Deploy code to a javacard of type gp211
Hey i have probleme to debloy to real java card, the code works in the emulator i have instal in netbeans but not in a real card, when i try it returns 6e00
My card is of type gp211, card reader is acs acr38 and iam using Netbeans IDE 7.4 and GPshell 1.4.4
My Script for gpshell is :
mode_211
enable_trace
establish_context
card_connect
select -AID a000000003000000
open_sc -security 1 -keyind 0 -keyver 0 -mac_key 404142434445464748494a4b4c4d4e4f -enc_key 404142434445464748494a4b4c4d4e4f // Open secure channel
delete -AID a00000006203010c0101
delete -AID a00000006203010c01
install -file Wallscript.cap -nvDataLimit 2000 -instParam 00 -priv 2
card_disconnect
release_context
And my code is :
package classicapplet1;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.OwnerPIN;
public class WallScript extends Applet {
/* constants declaration */
// code of CLA byte in the command APDU header
final static byte Wallet_CLA = (byte) 0x80;
final static byte staticpin[]={0x01,0x02,0x03,0x04,0x05};
// codes of INS byte in the command APDU header
final static byte VERIFY = (byte) 0x20;
final static byte CREDIT = (byte) 0x30;
final static byte DEBIT = (byte) 0x40;
final static byte GET_BALANCE = (byte) 0x50;
// maximum balance
final static short MAX_BALANCE = 0x7FFF;
// maximum transaction amount
final static byte MAX_TRANSACTION_AMOUNT = 127;
// maximum number of incorrect tries before the
// PIN is blocked
final static byte PIN_TRY_LIMIT = (byte) 0x03;
// maximum size PIN
final static byte MAX_PIN_SIZE = (byte) 0x08;
// signal that the PIN verification failed
final static short SW_VERIFICATION_FAILED = 0x6300;
// signal the the PIN validation is required
// for a credit or a debit transaction
final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
// signal invalid transaction amount
// amount > MAX_TRANSACTION_AMOUNT or amount < 0
final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6A83;
// signal that the balance exceed the maximum
final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6A84;
// signal the the balance becomes negative
final static short SW_NEGATIVE_BALANCE = 0x6A85;
OwnerPIN pin;
short balance;
private WallScript(byte[] bArray, short bOffset, byte bLength) {
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset + iLen + 1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset + cLen + 1);
byte aLen = bArray[bOffset]; // applet data length
pin.update(staticpin,(short)0,(byte)5);
register();
} // end of the constructor
public static void install(byte[] bArray, short bOffset, byte bLength) {
new WallScript(bArray, bOffset, bLength);
public boolean select() {
if (pin.getTriesRemaining() == 0) {
return false;
return true;
public void deselect() {
// reset the pin value
pin.reset();
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if (apdu.isISOInterindustryCLA()) {
if (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)) {
return;
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
if (buffer[ISO7816.OFFSET_CLA] != Wallet_CLA) {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
switch (buffer[ISO7816.OFFSET_INS]) {
case GET_BALANCE:
getBalance(apdu);
return;
case DEBIT:
debit(apdu);
return;
case CREDIT:
credit(apdu);
return;
case VERIFY:
verify(apdu);
return;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
private void credit(APDU apdu) {
if (!pin.isValidated()) {
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
U
byte numBytes = buffer[ISO7816.OFFSET_LC];
byte byteRead = (byte) (apdu.setIncomingAndReceive());
if ((numBytes != 1) || (byteRead != 1)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
byte creditAmount = buffer[ISO7816.OFFSET_CDATA];
// check the credit amount
if ((creditAmount > MAX_TRANSACTION_AMOUNT) || (creditAmount < 0)) {
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
if ((short) (balance + creditAmount) > MAX_BALANCE) {
ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
balance = (short) (balance + creditAmount);
private void debit(APDU apdu) {
if (!pin.isValidated()) {
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
byte numBytes = (buffer[ISO7816.OFFSET_LC]);
byte byteRead = (byte) (apdu.setIncomingAndReceive());
if ((numBytes != 1) || (byteRead != 1)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
byte debitAmount = buffer[ISO7816.OFFSET_CDATA];
if ((debitAmount > MAX_TRANSACTION_AMOUNT) || (debitAmount < 0)) {
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
if ((short) (balance - debitAmount) < (short) 0) {
ISOException.throwIt(SW_NEGATIVE_BALANCE);
balance = (short) (balance - debitAmount);
private void getBalance(APDU apdu) {
if (!pin.isValidated()) {
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
short le = apdu.setOutgoing();
if (le < 2) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
apdu.setOutgoingLength((byte) 2);
buffer[0] = (byte) (balance >> 8);
buffer[1] = (byte) (balance & 0xFF);
apdu.sendBytes((short) 0, (short) 2);
} // end of getBalance method
private void verify(APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte byteRead = (byte) (apdu.setIncomingAndReceive());
if (pin.check(buffer, ISO7816.OFFSET_CDATA, byteRead) == false) {
ISOException.throwIt(SW_VERIFICATION_FAILED);
Need help plsHello, we need apdu traces. "It doesn't work" is not enough. Thanks.
-
Sample Javacard 2.2.1 Electronic wallet, Loyalty Points & StudentID applet
Hi All,
After nine months of researching and developing a java card applet and terminal side interface for my final year university project I was frustrated with the lack of sample code and tutorials available online.
My applet is aimed at students as an id card containing a student id, all the features of an electronic wallet, loyalty point system protected by a pin number. Pin is changeable.
The terminal interaction or host side application that communicates with this applet can be found in this forum under the heading "Sample Smartcardio (Host side) applet interaction application".
As I have no finished my project I would like to share it with anyone that would like to see it.
While I would love to write a tutorial I simply do not have the time however below is the applet I used in my project, I how for anyone that has read through java sun's tutorials this will be a help:
package account;
import javacard.framework.APDU;
import javacard.framework.APDUException;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.OwnerPIN;
import javacard.framework.TransactionException;
import javacard.framework.Util;
* @Raymond_Garrett
* DT 354-4
*Applet ID 41 63 63 6F 75 6E 74 41 70 70 6C 65 74
public class AccountApplet extends Applet {
// codes of CLA byte in the command APDUs
final static byte ACCOUNT_CLA = (byte)0xA0;
// codes of INS byte in the command APDUs
final static byte VERIFY_INS = (byte) 0x20;
final static byte CREDIT_INS = (byte) 0x30;
final static byte DEBIT_INS = (byte) 0x40;
final static byte GET_LOYALTYPOINTS_BALANCE_INS = (byte) 0x45;
final static byte CREDIT_LOYALTYPOINTS_INS = (byte) 0x47;
final static byte GET_BALANCE_INS = (byte) 0x50;
final static byte UPDATE_PIN_INS = (byte) 0x60;
final static byte ADMIN_RESET_INS = (byte) 0x70;
final static byte PIN_TRIES_REMAINING_INS = (byte) 0x80;
final static byte STUDENT_NUMBER_INS = (byte) 0x90;
// maximum Account balance
final static short MAX_BALANCE = 10000;
// maximum transaction amount
final static short MAX_TRANSACTION_AMOUNT = 5000;
// maximum number of incorrect tries before the
// PIN is blocked
//Changed to 4, as a safe guard all. All tests, messages and checks will use 3
final static byte PIN_TRY_LIMIT =(byte)0x04;
// maximum size PIN
final static byte MAX_PIN_SIZE =(byte)0x08;
// Applet-specific status words:
final static short SW_NO_ERROR = (short) 0x9000;
final static short SW_VERIFICATION_FAILED = 0x6300;
final static short SW_PIN_VERIFICATION_REQUIRED = 0x6301;
final static short SW_INVALID_TRANSACTION_AMOUNT = 0x6E83;
final static short SW_EXCEED_MAXIMUM_BALANCE = 0x6E84;
final static short SW_NEGATIVE_BALANCE = 0x6E85;
final static short SW_PIN_TO_LONG = 0x6E86;
final static short SW_PIN_TO_SHORT = 0x6E87;
// Student number (Ascii)d05106012 - (Hex)44 30 35 31 30 36 30 31 32
private static byte[] STUDENT_NUMBER_ARRAY = {(byte)0x44, (byte)0x30, (byte)0x35, (byte)0x31, (byte)0x30, (byte)0x36, (byte)0x30, (byte)0x31, (byte)0x32};
// instance variables declaration
OwnerPIN pin;
short balance = 1000; // Starting balance of decimal 1000 is 3E8 in hex
short loyaltyPoints = 0; //Loyalty points
// 1 Loyalty point awarded for every 100 cent spent.
* install method
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new AccountApplet(bArray, (short) (bOffset + 1), bArray[bOffset]);
* Constructor
* @param bArray
* @param bOffset
* @param bLength
private AccountApplet(byte[] bArray, short bOffset, byte bLength){
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
// bArray contains the default PIN initialization value (12345)
bArray[0] = 01;
bArray[1] = 02;
bArray[2] = 03;
bArray[3] = 04;
bArray[4] = 05;
bOffset = 0;
bLength = 5;
pin.update(bArray, bOffset, bLength);
// register the applet instance with the JCRE
register();
} // end of the constructor
* Boolean is selected
public boolean select() {
// the applet declines to be selected
// if the pin is blocked
if (pin.getTriesRemaining() == 0)
return false;
return true;
} // end of select method
* deselect
public void deselect() {
// reset the pin
pin.reset();
* Key method the gets the APDU reads the INS and calls the appropiate method
* Process APDUs
* @param apdu
public void process(APDU apdu) {
// APDU object carries a byte array (buffer) to
// transfer incoming and outgoing APDU header
// and data bytes between the card and the host
// at this point, only the first five bytes
// [CLA, INS, P1, P2, P3] are available in
// the APDU buffer
byte[] buffer = apdu.getBuffer();
// return if the APDU is the applet SELECT command
if (selectingApplet())
return;
// verify the CLA byte
if (buffer[ISO7816.OFFSET_CLA] != ACCOUNT_CLA)
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
// check the INS byte to decide which service method to call
switch (buffer[ISO7816.OFFSET_INS]) {
case GET_BALANCE_INS: getBalance(apdu); return;
case DEBIT_INS: debit(apdu); return;
case CREDIT_INS: credit(apdu); return;
case VERIFY_INS: verify(apdu); return;
case UPDATE_PIN_INS: updatePin(apdu); return;
case ADMIN_RESET_INS: adminRest(); return;
case PIN_TRIES_REMAINING_INS: getPinTriesRemaining(apdu); return;
case STUDENT_NUMBER_INS: getStudentNumber(apdu); return;
case GET_LOYALTYPOINTS_BALANCE_INS: getLoyaltyPoints(apdu); return;
case CREDIT_LOYALTYPOINTS_INS: creditLoyaltyPoints(apdu); return;
default: ISOException.throwIt
(ISO7816.SW_INS_NOT_SUPPORTED);
} // end of process method
* verify then
* withdraw money from the Account balance
* @param apdu
private void debit(APDU apdu) {
// verify authentication
if (!pin.isValidated()){
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
// get the number of bytes in the
// data field of the command APDU
byte numBytes = buffer[ISO7816.OFFSET_LC];
//receive data
//data is read into apdu buffer
//at offset ISO7816.OFFSET_CDATA
byte byteRead = (byte)(apdu.setIncomingAndReceive());
short shortAmount = 0;
if (numBytes == 2){
shortAmount = (short) Util.getShort(buffer, ISO7816.OFFSET_CDATA);
else if (numBytes == 1) {
shortAmount = (short) buffer[ISO7816.OFFSET_CDATA];
// check the debit amount
if (( shortAmount > MAX_TRANSACTION_AMOUNT) || ( shortAmount < 0 )) {
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
// check the new balance
if ((short)( balance - shortAmount) < 0) {
ISOException.throwIt(SW_NEGATIVE_BALANCE);
// debit the amount
balance = (short)(balance - shortAmount);
//Add loyalty points
loyaltyPoints = (short) (loyaltyPoints + (short)(shortAmount/100));
return;
} // end of debit method
Code continued>>>>>>>>
* Verify then
* add money (credit) to the Account balance
* @param apdu
private void credit(APDU apdu) {
// verify authentication
if (!pin.isValidated()){
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
// get the number of bytes in the
// data field of the command APDU
byte numBytes = buffer[ISO7816.OFFSET_LC];
//receive data
//data is read into apdu buffer
//at offset ISO7816.OFFSET_CDATA
byte byteRead = (byte)(apdu.setIncomingAndReceive());
short shortAmount = 0;
if (numBytes == 2){
shortAmount = (short) Util.getShort(buffer, ISO7816.OFFSET_CDATA);
else if (numBytes == 1) {
shortAmount = (short) buffer[ISO7816.OFFSET_CDATA];
// check the credit amount
if (( shortAmount > MAX_TRANSACTION_AMOUNT) || ( shortAmount < 0 )) {
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
// check the new balance
if ((short)( balance + shortAmount) > MAX_BALANCE) {
ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
// credit the amount
balance = (short)(balance + shortAmount);
return;
} // end of deposit method
* Verify then
* Update/change pin
* byte[] bArray is the pin
* short bOffset is the position in the array the pin starts in the bArray
* byte bLength is the lenght of the pin
* @param apdu
private void updatePin(APDU apdu) {
// byte[] bArray, short bOffset, byte bLength){
// First check the original pin
// verify authentication
if (! pin.isValidated())
ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
byte[] buffer = apdu.getBuffer();
// get the number of bytes in the
// data field of the command APDU -- OFFSET_LC = positon 4
byte numBytes = buffer[ISO7816.OFFSET_LC];
// recieve data
// data are read into the apdu buffer
// at the offset ISO7816.OFFSET_CDATA
byte byteRead = (byte)(apdu.setIncomingAndReceive());
// error if the number of data bytes
// read does not match the number in the Lc byte
if (byteRead != numBytes) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
if ( numBytes > 8 )
ISOException.throwIt(SW_PIN_TO_LONG);
if ( numBytes < 4 )
ISOException.throwIt(SW_PIN_TO_SHORT);
short offset_cdata = 05;
pin.update(buffer, offset_cdata, numBytes);
pin.resetAndUnblock();
* Admin method
* Rest the pin attempts and unblock
* @param apdu
private void adminRest() {
try {
pin.resetAndUnblock();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
return;
* Credit loyatly card pints in multiples of 100
* @param apdu
private void creditLoyaltyPoints(APDU apdu) {
short creditAmount = (short) ((loyaltyPoints/ 100) * 100);
balance = (short) (balance + creditAmount);
loyaltyPoints = (short) (loyaltyPoints - creditAmount);
return;
* Get number of remaining pin tries
* @param apdu
private void getPinTriesRemaining(APDU apdu) {
try {
byte[] buffer = apdu.getBuffer();
// inform the JCRE that the applet has data to return
short le = apdu.setOutgoing();
// set the actual number of the outgoing data bytes
apdu.setOutgoingLength((byte)2);
// write the PinTriesRemaining into the APDU buffer at the offset 0
Util.setShort(buffer, (short)0, pin.getTriesRemaining());
// send the 2-byte balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
} catch (APDUException e) {
// TODO Auto-generated catch block
} catch (TransactionException e) {
// TODO Auto-generated catch block
} catch (ArrayIndexOutOfBoundsException e) {
// TODO Auto-generated catch block
} catch (NullPointerException e) {
// TODO Auto-generated catch block
} // end of getPinTriesRemaining method
* No verification needed
* the method returns the Accounts balance
* @param apdu
private void getBalance(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// inform the JCRE that the applet has data to return
short le = apdu.setOutgoing();
// set the actual number of the outgoing data bytes
apdu.setOutgoingLength((byte)2);
// write the balance into the APDU buffer at the offset 0
Util.setShort(buffer, (short)0, (balance));
// send the 2-byte balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
* No verification needed
* the method returns the Accounts loyaltyPoints balance
* @param apdu
private void getLoyaltyPoints(APDU apdu){
byte[] buffer = apdu.getBuffer();
// inform the JCRE that the applet has data to return
short le = apdu.setOutgoing();
// set the actual number of the outgoing data bytes
apdu.setOutgoingLength((byte)2);
// write the loyaltyPoints balance into the APDU buffer at the offset 0
Util.setShort(buffer, (short)0, (loyaltyPoints));
// send the 2-byte loyaltyPoints balance at the offset
// 0 in the apdu buffer
apdu.sendBytes((short)0, (short)2);
* No verification needed
* the method returns the student number
* @param apdu
private void getStudentNumber(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// inform the JCRE that the applet has data to return
short le = apdu.setOutgoing();
// set the actual number of the outgoing data bytes
apdu.setOutgoingLength((byte)STUDENT_NUMBER_ARRAY.length);
// write the balance into the APDU buffer at the offset 0
apdu.sendBytesLong(STUDENT_NUMBER_ARRAY, (short)0, (short) STUDENT_NUMBER_ARRAY.length);
// Util.setShort(buffer, (short)0, STUDENT_NUMBER_ARRAY);
// send the 2-byte balance at the offset
// 0 in the apdu buffer
try {
apdu.sendBytes((short)0, (short)STUDENT_NUMBER_ARRAY.length);
} catch (APDUException e) {
// TODO Auto-generated catch block
} // end of getBalance method
* Verification method to verify the PIN
* @param apdu
private void verify(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// receive the PIN data for validation.
byte byteRead = (byte)(apdu.setIncomingAndReceive());
// check pin
// the PIN data is read into the APDU buffer
// starting at the offset ISO7816.OFFSET_CDATA
// the PIN data length = byteRead
if (pin.check(buffer, ISO7816.OFFSET_CDATA,byteRead)
== false)
ISOException.throwIt(SW_VERIFICATION_FAILED);
} // end of verify method
} // end of class AccountEdited by: Raymond.garrett-Dublin on Jun 17, 2009 11:30 PM -
My application (in delphi) send Name(string), Family(string), And children (array of string)...
then These data will convert into Hex format and will be sent to CAD via APDU...
My question is how can I send all of these data at once via on APDU command, should I send Name and Family one by one and also send every index in my array one by one ??
I wrote an applet which has a SetName, Set Family and SetChildren Methods and once call SetName and send Name via one APDU, then call SetFamily and send Family via other APDU, and the big problem is in array that I'm sending each index data of array via one APDU...
I'm sure it's a foolish way and there's a better way to send these data :)
would u please help me and guid me what can I do, this is so much urgent
Kind Regards
HanaZip_Smart_Girl wrote:
first a question about your last reply:
I add this code in my applet process method, so what can i send from JCOP, can I now send Lc in 2 bytes ??The card you have is Java Card 2.2.1 which does not support extended length APDU's. As such your only choice is to implement chaining. This is also the reason why your code does not compile in Eclipse. You are building against the JC2.2.1 libraries.
Here is some code that may help you get started. This code is not tested (apart from the fact it compiles) as I am not at work at the moment. This code comes with all the standard disclaimers and may not be fit for purpose... so use at your own risk :) There is still more validation that could go in (such as checking that the GET-RESPONSE command has the same CLA byte etc). Hopefully this code works and gets you started with command and response chaining. This may also help anyone else that needs to do something similar. If this can help just one person I will be happy.
Cheers,
Shane
package chaining;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
* Very simple applet for chaining data to and from a card.
* @author shane
public class ChainingApplet extends Applet {
private final static byte INS_GET_RESPONSE = (byte) 0xC0;
private final static byte INS_PUT_DATA = 0x00;
private final static byte INS_GET_DATA = 0x01;
private final static byte OFFSET_SENT = 0x00;
private final static byte OFFSET_RECV = 0x01;
private static short[] offset;
private static byte[] fileBuffer;
private static short fileSize = 0;
private final static short FILE_SIZE = 2048; // 2KB file
private final static short MAX_APDU = 255;
* Default constructor that initialises all memory to be used by the applet.
public ChainingApplet() {
offset = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET);
fileBuffer = new byte[FILE_SIZE];
* {@inheritDoc}
public static void install(byte[] bArray, short bOffset, byte bLength) {
// GP-compliant JavaCard applet registration
new ChainingApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
* {@inheritDoc}
public void process(APDU apdu) {
// Good practice: Return 9000 on SELECT
if (selectingApplet()) {
return;
short len = apdu.setIncomingAndReceive(); // This is the amount of data read from the OS.
byte[] buf = apdu.getBuffer();
byte cla = buf[ISO7816.OFFSET_CLA];
byte ins = buf[ISO7816.OFFSET_INS];
short lc = (short) (buf[ISO7816.OFFSET_LC] & 0x00ff); // this is the LC from the APDU.
// get all bytes from the buffer
while (len < lc) {
len += apdu.receiveBytes(len);
// validate the INS byte (basic check that tests for valid GET-RESPONSE or GET-DATA)
if (offset[OFFSET_SENT] > 0 && ins != INS_GET_RESPONSE) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} else if (ins == INS_GET_RESPONSE && offset[OFFSET_SENT] == 0) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
switch (buf[ISO7816.OFFSET_INS]) {
case INS_PUT_DATA:
saveData(buf, ISO7816.OFFSET_CDATA, offset[OFFSET_RECV], len);
if ((cla & 0x10) != 0x00) {
offset[OFFSET_RECV] += len;
} else {
// last command in the chain
fileSize = (short) (offset[OFFSET_RECV] + len);
offset[OFFSET_RECV] = 0;
break;
case INS_GET_DATA:
case INS_GET_RESPONSE:
sendData(apdu);
break;
default:
// good practice: If you don't know the INStruction, say so:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
* Simple method to save the data somewhere. Add real implementation here.
* @param source
* buffer containing data to copy
* @param sourceOff
* offset into source buffer to the data
* @param destOff
* offset into the destination buffer
* @param len
* length of the data to copy.
private static void saveData(byte[] source, short sourceOff, short destOff, short len) {
// prevent buffer overflow
if ((short) (destOff + len) > FILE_SIZE) {
ISOException.throwIt(ISO7816.SW_FILE_FULL);
Util.arrayCopy(source, sourceOff, fileBuffer, destOff, len);
* Simple method to send chainined data to the client application (if required).
* @param apdu
* current APDU
private void sendData(APDU apdu) {
// work out how many bytes to send this time and how many will be left
short remain = (short) (fileSize - offset[OFFSET_SENT]);
boolean chain = remain > MAX_APDU;
short sendLen = chain ? MAX_APDU : remain;
// Get ready to send
apdu.setOutgoing();
apdu.setOutgoingLength(sendLen);
apdu.sendBytesLong(fileBuffer, offset[OFFSET_SENT], sendLen);
// Check to see if there are more APDU's to send
if (chain) {
offset[OFFSET_SENT] += sendLen; // count the bytes sent
ISOException.throwIt(ISO7816.SW_BYTES_REMAINING_00); // indicate there are more bytes to come
} else {
offset[OFFSET_SENT] = 0; // no more bytes to send
} -
I made a simple applet to test the speed of adding arrays, depending whether they are saved in EEPROM or RAM. Since working with variables stored in RAM should be faster, I was really surprised when I noticed no difference between them. I would really like to know where I went wrong, but simply can-t figure it out, so any help would be really appreciated. I used Eclipse 3.2 with JCOP Tools 3.1.1b and JCOP31 v2.2 JavaCard. The code I produced is:
package test;
import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Applet;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
public class SimpleMemoryTest extends Applet {
private static final short ARRAY_SIZE = 32;
byte[] eeprom_a, eeprom_b, eeprom_c;
byte[] ram_a, ram_b, ram_c;
short[] mem;
private SimpleMemoryTest() {
this.mem = new short[2];
public static void install(byte[] bArray, short bOffset, byte bLength) {
new SimpleMemoryTest().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
public void process(APDU apdu) {
if (selectingApplet()) return;
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00: { // Print memory info to verify where arrays are stored
mem[0] = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
mem[1] = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
buf[0] = (byte)(mem[0] / 256);
buf[1] = (byte)(mem[0] % 256);
buf[2] = (byte)(mem[1] / 256);
buf[3] = (byte)(mem[1] % 256);
apdu.setOutgoingAndSend((short)0, (short)4);
break;
case (byte) 0x01: { // Put arrays in EEPROM.
this.eeprom_a = new byte[ARRAY_SIZE];
this.eeprom_b = new byte[ARRAY_SIZE];
this.eeprom_c = new byte[ARRAY_SIZE];
break;
case (byte) 0x02: { // Put arrays in RAM.
this.ram_a = JCSystem.makeTransientByteArray(ARRAY_SIZE, JCSystem.CLEAR_ON_DESELECT);
this.ram_b = JCSystem.makeTransientByteArray(ARRAY_SIZE, JCSystem.CLEAR_ON_DESELECT);
this.ram_c = JCSystem.makeTransientByteArray(ARRAY_SIZE, JCSystem.CLEAR_ON_DESELECT);
break;
case (byte) 0x03: { // Add arrays in EEPROM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
eeprom_c[j] = (byte)(eeprom_a[j] + eeprom_b[j]);
break;
case (byte) 0x04: { // Add arrays in RAM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
ram_c[j] = (byte)(ram_a[j] + ram_b[j]);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}When you create a byte array, all values are initialized to 0. Looking at your loops, it seems you're adding 0's only. Smart card operating systems normally do a read before write, to make sure not the same value is written. It saves time, and in case of EEPROM also to prolong the lifetime. I think this is the reason why you see no difference .. because there is no writing. Do something like
eeprom_c[j] = (byte)(i + j);
Matjaz wrote: case (byte) 0x03: { // Add arrays in EEPROM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
eeprom_c[j] = (byte)(eeprom_a[j] + eeprom_b[j]);
break;
case (byte) 0x04: { // Add arrays in RAM 100 times
short i, j;
for (i = (short) 0; i < (short) 100; i++) {
for (j = (short) 0; j < (short) ARRAY_SIZE; j++) {
ram_c[j] = (byte)(ram_a[j] + ram_b[j]);
break;
Maybe you are looking for
-
Timeouts increased after we moved USR, SAP data files and TLogs to new SAN
We are having issues with timeouts after we moved our USR, SAP SQL Datafiles and SAP Transaction Logs from our old SAN to a new SAN. Timeouts for SAPGUI users are set to 10 minutes. We are running Windows Server 2003 with SQL Server 2005. The SAP dat
-
Windows AAMEE-created installer files install, then uninstall all products
I am trying to use AAMEE 3.1 to create CS6 installer files that will be used in creating a Windows 7 image. Every version of the installer file that I have tried does not work. In every case, the product(s) is installed and then subsequently uninsta
-
Importing jpeg's to Microsoft word
I am looking to import some jpeg's to word using activex, but i am having trouble doing that. need help on how to import a jpeg to labview.I do not have the office toolkit. thanks anand
-
Since my last update, 10.2.0.424, my camera just wont start up. I cant watch any videos either, not even on you tube? Everything was working fine on previous updates. Been sitting with this problem for a month now..waiting for new update to fix this
-
Move Macbook to Mac Mini?
This question has probably been asked numerous times, but I can't find it. Apologize for duplication. I have a Macbook I bought in Dec 2006. I've added a 500 GB drive and upgraded to 4 GB RAM. It's been an excellent computer, but I think it's feeling