Books
Smart Card Developers Kit - Macmillan
Scott B.Guthery & Timothy Jurgensen
ISBN: 1-57870-027-2
Web Sites
Multos - http://www.multos.com
JavaCard -
http://www.javasoft.com/products/javacard/index.html
WinCard -
http://www.microsoft.com/windowsce/smartcard/start/intro.asp
GSM Security Breach -
http://www.efc.ca/pages/crypto/smartcard.13apr98.html
ETSI (GSM Standards) - http://www.etsi.org/
Appendix B: JavaCard Example in Full
// Thanks to Dr Dobbs (http://www.ddj.com)
package article;
import javacard.framework.*;
public class Loyalty extends Applet {
// These attributes are made static because
they
// are referenced in the static install
method
protected static short sPoints = 0;
protected static byte[] baBuffer;
// CLA & INS definitions
public static final byte CLA_LOYALTY =
(byte)0xAA;
public static final byte INS_VALIDATE_PIN =
0x10;
public static final byte INS_GETBALANCE = 0x20;
public static final byte INS_DEBIT = 0x30;
public static final byte INS_CREDIT = 0x40;
// PIN attributes
public static final byte PIN_LENGTH = 8;
protected OwnerPIN pin;
protected static byte[] baPINValue = {0x0A, 0x0B,
0x0A, 0x0B,
0x0A, 0x0B, 0x0A, 0x0B};
protected transient boolean zIsAuthorized =
false;
public static void install(APDU _apdu) {
Loyalty loyalty = new
Loyalty();
// Initialize user PIN
loyalty.pin = new
OwnerPIN((byte)5, PIN_LENGTH);
loyalty.pin.updateAndUnblock(baPINValue, (short)0, PIN_LENGTH);
// Register the applet
loyalty.register();
}
public void process(APDU _apdu) {
// Get reference to apdu
buffer
byte[] baBuffer =
_apdu.getBuffer();
// Verify class
if(baBuffer[ISO.OFFSET_CLA] !=
CLA_LOYALTY)
ISOException.throwIt(ISO.SW_CLA_NOT_SUPPORTED);
// Branch to each instruction
switch(baBuffer[ISO.OFFSET_INS])
{
case
INS_VALIDATE_PIN:
this.validatePIN(_apdu);
break;
case
INS_DEBIT:
this.debit(_apdu);
break;
case INS_CREDIT:
this.credit(_apdu);
break;
case
INS_GETBALANCE:
this.getBalance(_apdu);
break;
}
}
protected void validatePIN(APDU _apdu) {
// Get reference to apdu
buffer
baBuffer = _apdu.getBuffer();
// Get data from terminal
byte bLc =
(byte)_apdu.setIncomingAndReceive();
// Check length being sent
if(bLc != PIN_LENGTH)
ISOException.throwIt(ISO.SW_WRONG_LENGTH);
// Validate PIN
if(pin.check(baBuffer,
ISO.OFFSET_CDATA, PIN_LENGTH))
zIsAuthorized =
true;
else
ISOException.throwIt(ISO.SW_SECURITY_STATUS_NOT_SATISFIED);
}
protected void debit(APDU _apdu) {
// Check if PIN is validated
if(!zIsAuthorized)
ISOException.throwIt(ISO.SW_SECURITY_STATUS_NOT_SATISFIED);
// Get reference to apdu
buffer
baBuffer = _apdu.getBuffer();
// Get data from terminal
byte bLc =
(byte)_apdu.setIncomingAndReceive();
// Get amount from apdu
buffer
short sAmount =
Util.getShort(baBuffer, ISO.OFFSET_P1);
// Don't allow negative
balance
if((sPoints - sAmount) <
0)
sPoints =
0;
else // debit account
sPoints =
(short)(sPoints - sAmount);
}
protected void credit(APDU _apdu) {
// Check if PIN is validated
if(!zIsAuthorized)
ISOException.throwIt(ISO.SW_SECURITY_STATUS_NOT_SATISFIED);
// Get reference to apdu
buffer
baBuffer = _apdu.getBuffer();
// Get data from terminal
byte bLc =
(byte)_apdu.setIncomingAndReceive();
// Get amount from apdu
buffer
short sAmount =
Util.getShort(baBuffer, ISO.OFFSET_P1);
// Increment balance
sPoints = (short)(sPoints +
sAmount);
}
protected void getBalance(APDU _apdu) {
// Check access permissions
if(!zIsAuthorized)
ISOException.throwIt(ISO.SW_SECURITY_STATUS_NOT_SATISFIED);
// Get reference to apdu
buffer
baBuffer = _apdu.getBuffer();
// Put balance value into apdu
buffer
Util.setShort(baBuffer,
ISO.OFFSET_CDATA, sPoints);
// Send balance
_apdu.setOutgoingAndSend(ISO.OFFSET_CDATA, (short)2);
}
}