GP Guidelines For Developing Apps On GP Cards V1.0a
GP Guidelines For Developing Apps On GP Cards V1.0a
GP Guidelines For Developing Apps On GP Cards V1.0a
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
Trademarks
Java Card is a registered trademark of Sun Microsystems, Inc.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
Table of Contents
1.
OVERVIEW..............................................................................................................................................5
1.1.
1.2.
2.
3.
4.
5.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
6.
7.
8.
COMMIT BUFFER................................................................................................................................38
TRANSIENT MEMORY.........................................................................................................................39
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
1.
1.1.
Overview
Purpose of this Document
The purpose of this document is to offer guidelines for developers who are
writing applications for Java Cards compliant to the GlobalPlatform Card
Specification Version 2.1.
The advantage of using GlobalPlatform functionality is explained, as are some
special requirements and restrictions that are specific to GlobalPlatform Java
Card based implementations. Information in this document focuses on smart
cards that implement Java Card 2.1.1 specifications and GlobalPlatform
Card Specification version 2.1 which supports both the 2.0.1 (Deprecated)
and 2.1 API.
The sample code and examples provided in this document are shown using
both the New and Deprecated API. The next version of this document will also
include examples that are leveraging the functionality provided only by the 2.1
API.
1.2.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
2.
2.1.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
2.2.
2.1 API:
private SecureChannel MySecureChannel;
...
public boolean select() {
MySecureChannel = GPSystem.getSecureChannel();
...
Deprecated API:
private ProviderSecurityDomain SecurityDomain;
...
public boolean select() {
SecurityDomain = OPSystem.getSecurityDomain();
...
2.2.2.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
important that the Application performs this check as the Security Domain will
not perform any checks over and above its own security policy as defined by its
owner (the Issuer or Application Provider). If the Security Domain security
policy does not require the presence of a C-MAC, when the Security Level
defined in the EXTERNAL AUTHENTICATE command indicates no Secure
Messaging (i.e. P1 parameter set to zero), there will be no secure messaging
checking by the Security Domain on subsequent commands, even if the Class
byte on a subsequent command has its bit 3 set to 1 (e.g. Class byte = 0x04 or
0x84).
Implicit Initiation mode: to be completed.
If an application wants to ensure that a command contains secure messaging
and that the command cryptographic protection is actually verified by the
Security Domain, the application must check the Security Level of the current
Secure Channel Session using the getSecurityLevel() method (no equivalent
method in the deprecated API beyond the application checking the value of P1
of the EXTERNAL AUTHENTICATE command). In other words, verifying that
the Class byte of a command has its bit 3 set to 1 is not sufficient by itself.
The Sample Application extract below shows the invocation of the
processSecurity() method (openSecureChannel() and
verifyExternalAuthenticate() methods in the deprecated API) for processing
the Secure Channel Protocol commands, regardless of the Secure Channel
Protocol supported by the Security Domain (SCP 01 or SCP 02). Please note
that in the deprecated API, the two Secure Channel Protocol commands:
INITIALIZE UPDATE and EXTERNAL AUTHENTICATE, must be recognized
by the application before being processed by the appropriate method.
2.1 API:
public void process( APDU apdu ) {
...
switch ( buffer[ISO7816.OFFSET_INS] ) {
// other commands recognized by the applet...
default: SCPcommands( apdu );
break;
}
return;
...
void SCPcommands ( APDU apdu ) {
responseLength = MySecureChannel.processSecurity( apdu );
if (responseLength != 0)
apdu.setOutgoingAndSend((short) ISO7816.OFFSET_CDATA, responseLength);
}
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
Deprecated API:
final static byte INS_INITIALIZE_UPDATE = (byte) 0x50;
...
public void process( APDU apdu ) {
...
switch ( buffer[ISO7816.OFFSET_INS] ) {
// other commands recognized by the applet...
case (byte) INS_INITIALIZE_UPDATE: initializeUpdate( apdu );
break;
case (byte) ISO7816.INS_EXTERNAL_AUTHENTICATE:
externalAuthenticate( apdu );
break;
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
}
return;
...
void initializeUpdate ( APDU apdu ) {
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
channel = SecurityDomain.openSecureChannel( apdu );
short responseLength = buffer[ISO7816.OFFSET_LC];
apdu.setOutgoingAndSend((short) ISO7816.OFFSET_CDATA, responseLength);
}
...
void externalAuthenticate ( APDU apdu ) {
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
SecurityDomain.verifyExternalAuthenticate( channel, apdu );
}
2.2.3.
2.1 API:
public void deselect() {
MySecureChannel.resetSecurity();
}
Deprecated API:
public void deselect() {
SecurityDomain.closeSecureChannel(channel);
}
10
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
2.2.4.
Unwrapping Commands
The application and the off-card entity must be synchronized as to which
commands contain secure messaging and which do not. Once a Secure Channel
Session has been initiated with a Security Level that indicates Secure
Messaging, the application can assume that any cryptographically protected
command received will be correctly unwrapped, its cryptographic protection
verified or, if not, the appropriate error response will be returned. If the
correct level of Secure Messaging has been applied to the command by the offcard entity, the unwrap() method will strip the command of its Secure
Messaging information, and present it back to the application for processing.
The following Sample Application extract demonstrates the use of unwrap()
method during personalization of the application .
2.1 API:
final static byte CLA_Proprietary_Secured = (byte) 0x84;
...
void personalize( APDU apdu ) {
...
byte[] buffer = apdu.getBuffer();
if( buffer[ ISO7816.OFFSET_CLA ] != CLA_Proprietary_Secured )
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
wrappedLength = apdu.setIncomingAndReceive();
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
...
Deprecated API:
final static byte CLA_Proprietary_Secured = (byte) 0x84;
...
void personalize( APDU apdu ) {
...
byte[] buffer = apdu.getBuffer();
if( buffer[ ISO7816.OFFSET_CLA ] != CLA_Proprietary_Secured )
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
apdu.setIncomingAndReceive();
SecurityDomain.unwrap(channel, apdu);
...
The above extract shows the case where the unwrapping of commands is
required during personalization. The Sample Application extract below shows
the unwrapping of the Change PIN command, when secure messaging is
indicated in the Class byte of the command header (i.e. bit 3 set to 1).
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
11
2.1 API:
void changePIN( APDU apdu ) {
...
byte[] buffer = apdu.getBuffer();
wrappedLength = apdu.setIncomingAndReceive();
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_Proprietary_Secured ) {
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
MyPIN.update(buffer, (short) ISO7816.OFFSET_CDATA,
buffer[ISO7816.OFFSET_LC], CVM.FORMAT_HEX);
...
Deprecated API:
void changePIN( APDU apdu ) {
...
byte[] buffer = apdu.getBuffer();
apdu.setIncomingAndReceive();
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_Proprietary_Secured )
SecurityDomain.unwrap(channel, apdu);
OPSystem.setPin( apdu, ISO7816.OFFSET_CDATA );
...
2.2.5.
Wrapping responses
To be completed
2.2.6.
12
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
The Sample Application extract below shows an application specific key block
being decrypted during the application personalization process. In this
example, the application specific key is presented to the card with the
GlobalPlatform PUT KEY command and a key check value, where the key
check value is formed of the 3 high order bytes resulting from encrypting a
block of 8 bytes of zeroes.
2.1 API:
private static DESKey verifKey;
private static Cipher DESInstance;
...
verifKey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_DESELECT,
KeyBuilder.LENGTH_DES, false);
DESInstance = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
...
boolean verifyKeyCheckValue (byte[] buffer, short keyOffset,
short checkValueOffset) {
byte[] checkValue = new byte[8];
Util.arrayFillNonAtomic(checkValue, (short) 0, (short) 8, (byte) 0 );
verifKey.setKey(buffer, keyOffset);
DESInstance.init(verifKey, Cipher.MODE_ENCRYPT);
DESInstance.doFinal(checkValue, (short) 0, (short) 8, checkValue,
(short) 0);
return (Util.arrayCompare(checkValue, (short) 0, buffer,
checkValueOffset, (short) 3) == (byte) 0);
}
...
void personalize( APDU apdu ) {
...
wrappedLength = apdu.setIncomingAndReceive();
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
MySecureChannel.decryptData(buffer, (short) (ISO7816.OFFSET_CDATA+3),
(short) (buffer[ISO7816.OFFSET_CDATA+2]) );
if (verifyKeyCheckValue(buffer, (short) (ISO7816.OFFSET_CDATA+3),
(short)(ISO7816.OFFSET_CDATA+4 + buffer[ISO7816.OFFSET_CDATA+2]) )
appletKey.setKey(buffer, (short) (ISO7816.OFFSET_CDATA+3));
...
Deprecated API:
void personalize( APDU apdu ) {
...
apdu.setIncomingAndReceive();
SecurityDomain.unwrap(channel, apdu);
if (SecurityDomain.decryptVerifyKey(channel,apdu,
(short)(ISO7816.OFFSET_CDATA+1))))
appletKey.setKey(buffer, (short)(ISO7816.OFFSET_CDATA+3));
...
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
2.2.7.
13
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
14
3.
3.1.
GlobalPlatform CVM
The GlobalPlatform CVM (or Global PIN in the deprecated API) functionality
is available on GlobalPlatform compliant cards as an option. GlobalPlatform
CVM provides a simple interface to a CVM data structure, and the controls
surrounding the CVM. Using this GlobalPlatform interface minimizes the
applications code by relieving the application from implementing PIN
management functions within its own code. It also improves the overall card
usability, since a common PIN may be used by multiple applications. Currently
the only supported CVM is a PIN.
An application may require the ability not only to verify that the CVM (PIN)
has been correctly presented, but may also require the ability to alter the value
of the CVM (PIN) block. If this is the case, the application must be installed
with the relevant CVM Management privilege, and the application should
contain code to verify that it is being installed with the required privilege. As
an enhancement to GlobalPlatform 2.0.1, GlobalPlatform 2.1 provides
additional CVM functionality that allows an application to set the maximum
retry limit as well as allowing an application to check if the PIN has been
previously presented within the current Card Session.
3.2.
2.1 API:
final static byte CVM_Management_Privilege = (byte) 0x02;
private CVM MyPIN;
...
public static void install(byte[] buffer, short offset, byte length) {
byte instanceLength = (byte) buffer[offset];
short instanceOffset = (short)(offset + 1);
byte appletPrivileges = (byte) buffer[
(short) (offset+1+instanceLength+1)];
if( appletPrivileges != CVM_Management_Privilege )
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
MyPIN = GPSystem.getCVM(GPSystem.CVM_GLOBAL_PIN);
if ( MyPIN == null )
ISOException.throwIt(Util.makeShort((byte) 0x6A, (byte) 0x88));
...
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
15
Deprecated API:
final static byte PIN_Change_Privilege = (byte) 0x02;
...
public static void install(byte[] buffer, short offset, byte length) {
byte instanceLength = (byte) buffer[offset];
short instanceOffset = (short)(offset + 1);
byte appletPrivileges = (byte) buffer[
(short) (offset+1+instanceLength+1)];
if( appletPrivileges != PIN_Change_Privilege ) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
...
See section 6.1 - Install() method for more information on the parameters of the
install() method.
3.2.2.
2.1 API:
public boolean select() {
...
MyPIN.resetState();
...
Deprecated API:
public boolean select() {
...
PINPresented = false;
...
3.2.3.
16
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
2.1 API:
void presentPIN( APDU apdu ) {
...
if ( MyPIN.isBlocked() )
ISOException.throwIt(Util.makeShort( (byte) 0x69, (byte) 0x83));
byte[] buffer = apdu.getBuffer();
wrappedLength = apdu.setIncomingAndReceive();
...
MyPIN.verify(buffer, (short) ISO7816.OFFSET_CDATA,
buffer[ISO7816.OFFSET_LC], CVM.FORMAT_HEX);
if ( !MyPIN.isVerified() ) {
byte triesRemaining = (byte) (MyPIN.getTriesRemaining() |
(byte) 0xc0);
ISOException.throwIt(Util.makeShort( (byte) 0x63, triesRemaining));
...
Deprecated API:
void presentPIN( APDU apdu ) {
...
if( OPSystem.getTriesRemaining() == 0 )
ISOException.throwIt(Util.makeShort( (byte) 0x69, (byte) 0x83));
byte[] buffer = apdu.getBuffer();
apdu.setIncomingAndReceive();
...
if( OPSystem.verifyPin( apdu, ISO7816.OFFSET_CDATA )){
PINPresented = true;
} else {
PINPresented = false;
byte triesRemaining = (byte) (OPSystem.getTriesRemaining() |
(byte) 0xc0);
ISOException.throwIt(Util.makeShort( (byte) 0x63, triesRemaining));
...
3.2.4.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
17
2.1 API:
void changePIN( APDU apdu ) {
if ( !MyPIN.isVerified() )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
byte[] buffer = apdu.getBuffer();
wrappedLength = apdu.setIncomingAndReceive();
...
MyPIN.update(buffer, (short) ISO7816.OFFSET_CDATA,
buffer[ISO7816.OFFSET_LC], CVM.FORMAT_HEX);
...
Deprecated API:
void changePIN( APDU apdu ) {
if ( PINPresented != true )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
byte[] buffer = apdu.getBuffer();
apdu.setIncomingAndReceive();
...
OPSystem.setPin( apdu, ISO7816.OFFSET_CDATA );
...
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
18
4.
4.1.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
4.2.
19
PERSONALIZED state
The application must set its own state to PERSONALIZED from the
state SELECTABLE. This action has to be initiated by an APDU destined for
the application, and should be completed prior to the application being used in
its intended environment. Typically, the application sets its Life Cycle State to
PERSONALIZED after it has received sufficient personalization information
(e.g. application specific keys and data).
4.2.2.
BLOCKED state
An application can transition its Life Cycle State to BLOCKED in the case
where it might want to limit some of its functionality. This could be either
before or after the application had reached the PERSONALIZED state.
It is the application itself that has the responsibility to limit its own
functionality when in the BLOCKED state.
Once in the state BLOCKED, the application may contain functionality that
allows it to return to its Life Cycle State prior to being set to the BLOCKED
state.
4.3.
20
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
2.1 API:
final static byte APPLET_PERSONALIZED = (byte) 0x0F;
...
void personalize( APDU apdu ) {
...
MySecureChannel.decryptData(buffer, (short) (ISO7816.OFFSET_CDATA+3),
(short) (buffer[ISO7816.OFFSET_CDATA+2]) );
if (verifyKeyCheckValue(buffer, (short) (ISO7816.OFFSET_CDATA+3),
(short)(ISO7816.OFFSET_CDATA+4 + buffer[ISO7816.OFFSET_CDATA+2])){
appletKey.setKey(buffer, (short) (ISO7816.OFFSET_CDATA+3));
GPSystem.setCardContentState( APPLET_PERSONALIZED );
} else {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
...
Deprecated API:
void personalize( APDU apdu ) {
...
if( SecurityDomain.decryptVerifyKey(channel,apdu,ISO7816.OFFSET_CDATA) ){
appletKey.setKey(buffer, (short)(ISO7816.OFFSET_CDATA+3));
OPSystem.setCardContentState( OPSystem.APPLET_PERSONALIZED );
} else {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
...
4.4.
2.1 API:
if ((GPSystem.getCardState()) == GPSystem.CARD_SECURED ) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
...
Deprecated API:
if ((OPSystem.getCardManagerState()) == OPSystem.CARD_SECURED ) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
...
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
4.5.
21
Locking the card disables all applications on the card and allows only the
Issuer Security Domain to process commands. This state is reversible from
within the Issuer Security Domain.
Terminating the card disables the card to the extent that only the GET
DATA command is processed and this state is not reversible.
For applications with the required privileges, an API is available to set the Life
Cycle State of the card to CARD_LOCKED and another API is available to
terminate the card. If an application needs to exercise this functionality, it
should contain code to verify that it is being installed with the appropriate
privilege during its installation.
The Sample Application demonstrates a similar processing of Application
Privileges as it applies to the verification of the CVM Management privilege
(see section 3.2.1 - Verifying the CVM Management Privilege).
22
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
5.
5.1.
Overview
This chapter describes how GlobalPlatform Life Cycle States may be applied to
implement application specific policies and risk management. The focus of this
chapter is on how Application Providers may implement risk management for
their specific application.
5.2.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
5.3.
23
Sample Application
In order to illustrate the use of Life Cycle States for risk management an
example application is provided: a Loyalty Application. The Loyalty
Application will allow the cardholder to collect and redeem points stored on the
card. Collecting and redeeming points is achieved using commands that add or
subtract the requested value from the on-card value. For the purpose of this
document it is assumed that the card reader implements this application logic.
This focus of this document is to describe the on-card implementation.
The Loyalty Application implements:
5.4.
It is not recommended that the application stores the Card Life Cycle State. As
the Card Life Cycle Sate may change at some point in time unknown to the
application, the Card Life Cycle State should be requested each time directly
from the GlobalPlatform API when needed.
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
24
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
5.5.
5.6.
5.6.1.
SELECTABLE: In this Life Cycle State the application has been first
instantiated and made selectable.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
25
26
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
5.6.2.
The VERIFY command may present an incorrect Password too often. Once
the retry counter expires, the Application transitions its own Life Cycle
State to BLOCKED.
The COLLECT, REDEEM and VERIFY commands may only be used in the
PERSONALIZED Life Cycle State.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
27
Deprecated API:
check_CARD_SECURED();
if ((AppletPW.check(buffer, ISO7816.OFFSET_CDATA,
(byte)buffer[ISO7816.OFFSET_LC])) == false) {
if ((AppletPW.getTriesRemaining()) == (byte) 1) {
OPSystem.setCardContentState(OPSystem.APPLET_BLOCKED);
}
}
...
private void check_CARD_SECURED () {
if ((OPSystem.getCardManagerState()) != OPSystem.CARD_SECURED ) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
}
...
5.6.3.
2.1 API:
final static byte APPLET_PERSONALIZED = (byte) 0x0F;
final static byte APPLET_BLOCKED = (byte) 0x7F;
...
if (bAppletLifeCycle == APPLET_BLOCKED) {
if (bNewAppletLifeCycle != APPLET_PERSONALIZED) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
}
GPSystem.setCardContentState(bNewAppletLifeCycle);
...
Deprecated API:
if (bAppletLifeCycle == OPSystem.APPLET_BLOCKED) {
if (bNewAppletLifeCycle != OPSystem.APPLET_PERSONALIZED) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
}
OPSystem.setCardContentState(bNewAppletLifeCycle);
...
28
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
5.7.
5.7.1.
In the SECURED Card Life Cycle State, the card has been issued to
the cardholder: it is a post-issuance Card Life Cycle State. The
following conclusions may be drawn:
o
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
29
It should not be concluded from this that the application does not need any
security when processing commands during these Card Life Cycle States.
Rather, the application may assume commands received have been or are
generated by a known entity. Identifying and authenticating this entity once at
the beginning of the session e.g. of the personalization sequence can be
considered sufficient for the whole operation.
5.7.2.
5.7.3.
30
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
The Life Cycle related risk management policies are applied to the command
processing as follows:
If the Card Life Cycle State is not SECURED, the application only
executes pre-issuance personalization commands.
o
In addition to the Card Life Cycle dependant risk management, the application
implements functional risk management policies. They are applied to the
command execution as follows:
The following table gives an overview of all the Loyalty Application risk
management policies.
APDU
STORE_DATA
COLLECT
Function
Application
personalization
(set Password)
Add loyalty points
REDEEM
VERIFY
Perform cardholder
verification using
application Password
Risk Management
Card state: pre-issuance
Application state: selectable
Other: none
Card state: post-issuance
Application state: personalized
Other: Password verified
Card state: post-issuance
Application state: personalized
Other: Password verified
Card state: post-issuance
Application state: personalized
Other: Password verified
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
31
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
32
6.
6.1.
Install() method
The install method is responsible for instantiating the application, assigning
data space (if required) and registering the application. The parameters passed
to this method by a GlobalPlatform compliant runtime environment have the
following format:
Byte array
A buffer of unknown length and format containing at least the
following consecutive data:
Field
Length of instance AID
Instance AID
Length of application privileges
Application privileges
Length of application specific parameters
Application specific parameters
Length
1
5-16
1
1
1
variable
Offset
An offset within the buffer pointing to the length of the instance AID.
Length
A length indicating the length of all the above defined consecutive data
at least encompassing the application specific parameters.
The instance AID must be used by the application to register itself in the Open
Platform Registry. This is done by invoking the register( byte[] bArray, short
bOffset, byte bLength ) method and should be the last function performed prior
to the install() method returning control to the JCRE.
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
33
The install() method of the Sample Application extract below shows the
constructor method being called.
public static void install(byte[] buffer, short offset, byte length) {
new Sample(buffer, offset, length);
34
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
6.2.
Select() method
The application becomes the current context following the successful invocation
of the select() method of the application by the JCRE. This could occur either
through the receipt of a SELECT command or due to the application being the
default selectable application. The default select() method implementation
provided by the applet class returns true. If the application implements its
own select() method, proper care must be taken to ensure that the select()
method does not fail for any reason whatsoever (i.e. does not throw an
exception), and that this method also always returns true.
Throwing an exception in the select() method, or returning false from the
select() method, will prevent the JCRE from proceeding with the application
selection. The errors returned to the terminal by the JCRE in these cases are
Java Card specific (not defined by ISO 7816-4).
If it is desired to prevent an application instance from being selected, a SET
STATUS command should be sent to the Issuer Security Domain to change the
Life Cycle State for that application instance to LOCKED.
The select() method of the Sample Application extract below has no conditions
which would cause this method to return false.
2.1 API:
public boolean select() {
MySecureChannel = GPSystem.getSecureChannel();
MyPIN.resetState();
return true;
}
...
Deprecated API:
public boolean select() {
SecurityDomain = OPSystem.getSecurityDomain();
PINPresented = false;
return true;
}
...
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
6.3.
35
Deselect() method
If a application has established a GlobalPlatform Secure Channel Session, it
must invoke the resetSecurity() method (closeSecureChannel() method in the
deprecated API) in its deselect() method. This is to ensure that the Secure
Channel Session will not be available to a different application that might be
selected.
2.1 API:
public void deselect() {
MySecureChannel.resetSecurity();
}
Deprecated API:
public void deselect() {
closeSecureChannel(channel);
}
6.4.
Process() method
When the application is the current context (i.e. selected), all APDU commands
are directed by the JCRE to the process() method of the application.
6.4.1.
36
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
If this method returns false, the application must first determine if it has
knowledge on how to handle the particular SELECT command (also
application specific) else it must return one of the following errors: 67 00 invalid length, 6A 86 - invalid P1/P2, 6A 81- function not supported or 6A 82
- application/file not found.
The Sample Application extract shown below provides a simple example of
spurious SELECT command management.
An EMV compliant application responding to a successful SELECT command
with an FCI containing the DF name (AID) of the application, must ensure
that the full AID is being returned. An application developer has 2 options:
Construct the FCI during the installation process using the instance AID
as the DF name; or,
Invoke the getAID() method while processing the SELECT command and
use this object for the DF name.
The developer must not use the AID of the data field of the command message
as the received SELECT command may have the partial select option set. In
this case the full AID may not be present in the data field.
The Sample Application extract below shows the coding of the second option
above.
void processSelect( APDU apdu ) {
if( !selectingApplet() ) {
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
short offset = ISO7816.OFFSET_CDATA;
short AIDLength =
JCSystem.getAID().getBytes(buffer, (short)(offset+4));
buffer[offset] = (byte) FCI_Template;
buffer[offset+1] = (byte)(4+AIDLength);
buffer[offset+2] = (byte) AID_Tag;
buffer[offset+3] = (byte) AIDLength;
buffer[offset+4+AIDLength] = (byte) Proprietary_Data_Template;
apdu.setOutgoingAndSend( (short) ISO7816.OFFSET_CDATA,
(short) (6+AIDLength) );
}
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
6.4.2.
37
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
38
7.
7.1.
Commit Buffer
Transactions on a Java Card are usually bracketed by application calls to
JCSystem.beginTransaction() and JCSystem.commitTransaction(). The JCRE
maintains an atomic transaction commit buffer. During a transaction, the
JCRE journal changes to persistent memory in this buffer so that it can
guarantee the atomicity of the transaction. The commit buffer is contained in
persistent memory, but is usually limited to a few hundred bytes. The amount
of overhead required to journal any particular change to persistent memory is
implementation specific, so it is difficult to determine how much of the commit
buffer a given transaction will use.
The following are several techniques that may help to reduce usage of the
commit buffer.
Be aware that many JCRE implementations also use the commit buffer to
journal changes made during the install() method. Developers need to be
particularly careful not to cause the commit buffer to overflow during the
install() method, since this will make it impossible to install the application.
Some implementations may require more than 8 bytes of the commit buffer to
journal each new operation. Therefore, designing an application with
extremely complex objects that need to be instantiated may prevent the
application from being installed on some cards.
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
7.2.
39
Transient Memory.
Transient Objects, although normally allocated in RAM, are guaranteed to
continue to exist so long as they can be referenced. The description transient
more accurately refers to the data contents of the object, which may be cleared,
rather than the object itself. The area of RAM allocated in a given application
for a Transient Object may not be available for use by other applications on the
card.
40
8.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
GlobalPlatform APIs
This chapter describes the mapping of GlobalPlatform Deprecated API onto
GlobalPlatform 2.1 API.
The export and related files for the 2.1 API can be obtained from
GlobalPlatform website (http://www.globalplatform.org) within the Supporting
Documentation section or within the Card-Related Chip Technology section.
The export and related files for the Deprecated API can be obtained from the
GlobalPlatform website within the Previous GlobalPlatform Versions section.
Deprecated API
2.1 API
Description
visa.openplatform
org.globalplatform
Package name
A0 00 00 00 03 00 00
A0 00 00 01 51 00 00
Package AID
Class OPSystem
Class GPSystem
byte getCardContentState ()
boolean
setCardContentState
(byte bState)
byte getCardManagerState
()
byte getCardState ()
boolean lockCardManager ()
boolean lockCard ()
boolean
terminateCardManager ()
boolean terminateCard ()
boolean setATRHistBytes
(byte[] buffer, short sOffset,
byte bLength)
boolean setATRHistBytes
(byte[] baBuffer, short sOffset,
byte bLength)
ProviderSecurityDomain
getSecurityDomain ()
SecureChannel
getSecureChannel ()
N/A
CVM getCVM
(byte[] baCVMIdentifier)
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
Deprecated API
2.1 API
41
Description
Class OPSystem
Interface CVM
byte getTriesRemaining ()
byte getTriesRemaining ()
boolean verifyPIN
(APDU apdu, short pOffset)
short verify
(byte[] baBuffer, short sOffset,
byte bLength, byte bFormat)
boolean setPIN
(APDU apdu, short pOffset)
boolean update
(byte[] baBuffer, short sOffset,
byte bLength, byte bFormat)
N/A
short setTryLimit
(byte[] bTryLimit)
N/A
boolean blockState ()
N/A
boolean resetState ()
N/A
boolean
resetAndUnblockState ()
N/A
boolean isActive ()
N/A
boolean isBlocked ()
N/A
boolean isSubmitted ()
N/A
boolean isVerified ()
42
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
Deprecated API
2.1 API
Description
Interface
ProviderSecurityDomain
Interface SecureChannel
byte openSecureChannel
(APDU apdu)
short processSecurity
(APDU apdu)
void
short processSecurity
verifyExternalAuthenticate (APDU apdu)
(byte channel, APDU apdu)
void closeSecureChannel
(byte channel)
void resetSecurity ()
boolean decryptVerifyKey
(byte channel, APDU apdu,
short offset)
short decryptData
(byte[] baBuffer, short sOffset,
short sLength)
void unwrap
(byte channel, APDU apdu)
short unwrap
(byte[] baBuffer, short sOffset,
short sLength)
N/A
short wrap
(byte[] baBuffer, short sOffset,
short sLength)
N/A
short encryptData(byte[]
baBuffer, short sOffset, short
sLength)
N/A
byte getSecurityLevel ()
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
43
javacard.framework.ISO7816;
javacard.framework.ISOException;
javacard.framework.Util;
javacard.framework.Applet;
javacard.framework.APDU;
javacard.framework.JCSystem;
javacard.security.DESKey;
javacardx.crypto.Cipher;
javacard.security.KeyBuilder;
import org.globalplatform.*;
public class Sample extends Applet {
// Commands the applet implements
final static byte CLA_Proprietary = (byte) 0x80;
final static byte CLA_Proprietary_Secured = (byte) 0x84;
final static byte CLA_ISO7816_Secured = (byte) 0x04;
final static byte INS_VERIFY = (byte) 0x20;
final static byte INS_CHANGE_PIN = (byte) 0x24;
final static byte INS_PUT_KEY = (byte) 0xD8;
final static byte INS_GET_STATUS = (byte) 0xF2;
// Mask the secure messaging bit 3 of the Class byte
final static byte SM_MASK = (byte) 0xFB;
// Constants for the applets Select response string
final static byte FCI_Template = (byte) 0x6F;
final static byte AID_Tag = (byte) 0x84;
final static byte Proprietary_Data_Template = (byte) 0xA5;
// Application specific Life Cycle State of the applet
final static byte APPLET_PERSONALIZED = (byte) 0x0F;
// This application example makes use of the Global PIN provided by the GlobalPlatform
// CVM Interface. The CVM State keeps track of whether the PIN has been presented
// correctly from one APDU to the next. For this example it is explicitly reset
// each time the application is selected, regardless if it was previously presented
// (correctly or not) during the current card session.
final static byte CVM_Management_Privilege = (byte) 0x02;
private CVM MyPIN;
// The next statements are only required if Security Domain features are being used by
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
44
/* Applet constructor
*
The constructor for the applet would typically be where objects to be
*
used by the applet would be instantiated but not necessarily populated.
*
For the purpose of this example code, the only function of the constructor
*
is to register itself with the instance AID defined by the off-card
*
entity.
*
@ Parameters
*
buffer :- buffer containing at least the instance AID and application
*
privileges.
*
offset :- offset within the buffer pointing to the beginning of the
*
instance AID length.
*
length :- length of the install parameters within the buffer.
**/
protected Sample(byte[] buffer, short offset, byte length) {
// Determine the length of the instance AID.
byte instanceLength = (byte) buffer[offset];
// Locate the install privileges.
byte appletPrivileges = (byte) buffer[
(short) (offset+1+instanceLength+1)];
// Ensure that the applet has CVM Management permission.
if ( appletPrivileges != CVM_Management_Privilege )
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
// Ensure that the card implements the CVM Interface
MyPIN = GPSystem.getCVM(GPSystem.CVM_GLOBAL_PIN);
if ( MyPIN == (CVM) null )
ISOException.throwIt(Util.makeShort((byte) 0x6A, (byte) 0x88));
appletKey
/* Install method
*
As defined in the Java Card specifications and invoked by the JCRE on receipt
*
of an INSTALL [for instal]l command as defined in GlobalPlatform specifications
*
Parameters
*
buffer :- buffer containing at least the length and values of the
*
following: instance AID, application privileges and
*
application specific parameters
*
offset :- offset within the buffer pointing to the beginning of the
*
install parameters i.e. instance AID length.
*
length :- length of the install parameters within the buffer.
*
Note that this example applet does not utilize application specific parameters.
**/
public static void install(byte[] buffer, short offset, byte length) {
}
/*
// Applet constructor
new Sample(buffer, offset, length);
Select method
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
45
*
As defined in the Java Card specifications and invoked by the JCRE on receipt
*
of a SELECT command indicating this applet's instance.
*
Please note that it is advised that, for Global Platform, minimal code, if any,
*
be contained in this method and that for no reason should this method ever fail
*
or return false rather than true.
**/
public boolean select() {
// Retrieve the handle of the Security Domain associated with this applet.
MySecureChannel = GPSystem.getSecureChannel();
// Reset the CVM State of the Global PIN, regardless if the PIN has been previously
// presented (correctly or not) during the current card session. This example
// requires that the PIN be systematically (re)presented to the application.
MyPIN.resetState();
return true;
/* Deselect method
* calling resetSecurity() will ensure that if a Secure Channel Session
* has been established, it will not be available to another application.
* If a Secure Channel Session has not been established, this call will have no
* effect
*/
public void deselect() {
MySecureChannel.resetSecurity();
}
/* Process method
*
As defined in the Java Card specifications and invoked by the JCRE on
*
receipt of a command intended for the applet. The applet is responsible
*
for processing or dispatching each command.
*
Parameters
*
apdu :- the apdu buffer.
**/
public void process( APDU apdu ) {
// Generally commands are dispatched within an application according to
// their class and instruction bytes. Secure messaging is checked by
// individual methods.
byte[] buffer = apdu.getBuffer();
byte cla = (byte) (buffer[ ISO7816.OFFSET_CLA ] & (byte) SM_MASK);
byte ins = buffer[ ISO7816.OFFSET_INS ];
// ISO class
if( cla == ISO7816.CLA_ISO7816 ){
switch ( buffer[ISO7816.OFFSET_INS] ) {
// SELECT Command
case (byte) ISO7816.INS_SELECT: processSelect( apdu );
break;
// PRESENT PIN command
case (byte) INS_VERIFY: presentPIN( apdu );
break;
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
} /* end switch */
return;
}
// Proprietary class commands
if( cla == CLA_Proprietary ){
switch ( buffer[ISO7816.OFFSET_INS] ) {
// PUT KEY command
case (byte) INS_PUT_KEY: personalize( apdu );
break;
// CHANGE PIN command
case (byte) INS_CHANGE_PIN: changePIN( apdu );
break;
// GET STATUS command
case (byte) INS_GET_STATUS: getStatus( apdu );
break;
// Command not directly supported by the applet: it might be a Secure Channel
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
46
// Protocol command
default: SCPcommands( apdu );
break;
} /* end switch */
return;
}
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
/*
processSelect method
*
Method to handle the SELECT command.
*
Parameters
*
apdu :- the apdu buffer.
**/
void processSelect( APDU apdu ) {
// As the JCRE dispatches SELECT commands which cannot be accessed through the
// registry to the currently selected applet, the applet must insure it is being
// selected prior to responding.
if( !selectingApplet() ) {
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}
// Even though the command message has already been received by the JCRE, for
// consistency a pseudo receive is performed.
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
// Retrieve the complete AID of the selected applet and build the Select
// response string.
short offset = ISO7816.OFFSET_CDATA;
short AIDLength =
JCSystem.getAID().getBytes(buffer, (short)(offset+4));
buffer[offset] = (byte) FCI_Template ;
buffer[offset+1] = (byte)(4+AIDLength);
buffer[offset+2] = (byte) AID_Tag;
buffer[offset+3] = (byte) AIDLength;
buffer[offset+4+AIDLength] = (byte) Proprietary_Data_Template;
buffer[offset+4+AIDLength+1] = (byte) 0x00;
apdu.setOutgoingAndSend( (short) ISO7816.OFFSET_CDATA, (short) (6+AIDLength) );
/* SCPcommands method
*
Method to handle the Secure Channel Protocol commands defined in the
*
GlobalPlatform specifications, such as: INITIALIZE UPDATE and EXTERNAL
*
AUTHENTICATE commands.
*
The processing for these commands is performed by the Security Domain
*
associated with the application.
*
Errors are managed and output by the Security Domain.
*
Parameters
*
apdu :- the apdu buffer.
**/
void SCPcommands ( APDU apdu ) {
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
47
/* personalize method
*
Method to handle the personalization (PUT KEY) command.
*
The personalization command requires secure messaging and contains
*
one single length key data object formatted according to the
*
GlobalPlatform specifications.
*
Parameters
*
apdu :- the apdu buffer.
**/
void personalize( APDU apdu ) {
// The applet checks its own state to insure it is not already personalized.
if( GPSystem.getCardContentState() != GPSystem.APPLICATION_SELECTABLE )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
// The applet expects some kind of secure messaging i.e. MAC or MAC and encryption.
byte[] buffer = apdu.getBuffer();
if( buffer[ ISO7816.OFFSET_CLA ] != CLA_Proprietary_Secured )
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
// The personalization data is retrieved and the command is unwrapped by the
// Security Domain.
// Errors in the unwrapping process are managed and output by the Security Domain.
wrappedLength = apdu.setIncomingAndReceive();
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
// The command is now in an unwrapped state and the key can now be decrypted
// by the Security Domain. The applet is responsible for verifying the key check
// value of the key and for determining the action taken if the key cannot be
// verified.
MySecureChannel.decryptData(buffer, (short) (ISO7816.OFFSET_CDATA+3),
(short) (buffer[ISO7816.OFFSET_CDATA+2]) );
//
//
//
//
if
{
The applet is responsible for verifying the key check value of the key and
for determining the action taken if the key check value does not match.
This example sets the key as the applet key if the verification is correct and
throws an error if not.
(verifyKeyCheckValue(buffer, (short) (ISO7816.OFFSET_CDATA+3),
(short)(ISO7816.OFFSET_CDATA+4 + buffer[ISO7816.OFFSET_CDATA+2]) ))
appletKey.setKey(buffer, (short) (ISO7816.OFFSET_CDATA+3));
/* getStatus method
*
Method to handle the Get Status command.
*
The Get Status command may or may not include secure messaging and returns
*
the status of the application to the off-card entity.
*
Parameters
*
apdu :- the apdu buffer.
**/
void getStatus( APDU apdu ) {
byte[] buffer = apdu.getBuffer();
// Only if the command includes secure messaging will it contain a command
// message i.e. a MAC. In which case the command message must be retrieved
// and the command unwrapped.
// Errors in the unwrapping process are managed and output by the Security
// Domain.
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_Proprietary_Secured ){
wrappedLength = apdu.setIncomingAndReceive();
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
}
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
48
// The application Life Cycle State is retrieved and output to the external entity.
buffer[ISO7816.OFFSET_CDATA] = GPSystem.getCardContentState();
apdu.setOutgoingAndSend( (short) ISO7816.OFFSET_CDATA, (short) 1 );
/* presentPIN method
*
Method to handle the present PIN command.
*
The present PIN command checks that the PIN presented by the external entity
*
to the card is valid. As this is the global PIN, the applet assumes that
*
the PIN has been previously populated.
*
Parameters
*
apdu :- the apdu buffer.
**/
void presentPIN( APDU apdu ) {
// PIN presentation can only occur when the application is in its own state
// Personalized.
if( GPSystem.getCardContentState() != APPLET_PERSONALIZED )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
// If the CVM State of the PIN is blocked, i.e. its retry limit has been reached,
// an appropriate error is thrown.
if( MyPIN.isBlocked() )
ISOException.throwIt(Util.makeShort( (byte) 0x69, (byte) 0x83));
// Retrieve the PIN data and unwrap the command if secure messaging is present.
byte[] buffer = apdu.getBuffer();
wrappedLength = apdu.setIncomingAndReceive();
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_ISO7816_Secured )
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
// The applet assumes that the PIN formatting required by the verify() method has
// been applied by the off-card entity and uses the transparent HEX format.
MyPIN.verify(buffer, (short) ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC],
CVM.FORMAT_HEX);
// If PIN verification failed, an appropriate error indicating how many
// opportunities remain to present the correct PIN will be thrown.
if ( !MyPIN.isVerified() ) {
byte triesRemaining = (byte) (MyPIN.getTriesRemaining () | (byte) 0xc0 );
/* changePIN method
*
Method to handle the change PIN command.
*
The change PIN command allows the Global PIN to be changed if the correct
*
PIN has been previously presented.
*
Parameters
*
apdu :- the apdu buffer.
**/
void changePIN( APDU apdu ) {
// The PIN must have been previously presented.
if ( !MyPIN.isVerified() )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
// Retrieve the command data
byte[] buffer = apdu.getBuffer();
wrappedLength = apdu.setIncomingAndReceive();
// unwrap if secure messaging is present
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_Proprietary_Secured )
MySecureChannel.unwrap(buffer, (short) ISO7816.OFFSET_CLA,
(short) (wrappedLength+5));
// The applet assumes that the correct PIN formatting has been applied by the
// off-card entity and uses the transparent HEX format.
MyPIN.update(buffer, (short) ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC],
CVM.FORMAT_HEX);
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
49
50
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
$Workfile: Sample.java $
$Date: 04/13/00 $
$Revised: 10/21/02 $
*/
import
import
import
import
import
import
import
import
import
javacard.framework.ISO7816;
javacard.framework.ISOException;
javacard.framework.Util;
javacard.framework.Applet;
javacard.framework.APDU;
javacard.framework.JCSystem;
javacard.security.DESKey;
javacardx.crypto.Cipher;
javacard.security.KeyBuilder;
import visa.openplatform.*;
public class Sample extends Applet {
// Commands the applet implements
final static byte CLA_Proprietary = (byte) 0x80;
final static byte CLA_Proprietary_Secured = (byte) 0x84;
final static byte CLA_ISO7816_Secured = (byte) 0x04;
final static byte INS_INITIALIZE_UPDATE = (byte) 0x50;
final static byte INS_VERIFY = (byte) 0x20;
final static byte INS_CHANGE_PIN = (byte) 0x24;
final static byte INS_PUT_KEY = (byte) 0xD8;
final static byte INS_GET_STATUS = (byte) 0xF2;
// Mask the secure messaging bit 3 of the Class byte
final static byte SM_MASK = (byte) 0xFB;
// Constants for the applets Select response string
final static byte FCI_TEMPLATE = (byte) 0x6F;
final static byte AID_Tag = (byte) 0x84;
final static byte Proprietary_Data_Template = (byte) 0xA5;
// The PINPresented flag is only required if an application makes use of the
// Global PIN. This flag keeps track of whether the PIN has been presented
// correctly from one APDU to the next. For this example it is explicitly
// set to false each time the application is selected. Alternatively, this
// could be a transient object in which case it would be automatically reset.
final static byte PIN_Change_Privilege = (byte) 0x02;
protected boolean PINPresented;
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
51
// The next 2 statements are only required if Security Domain features are being
// used by the application. The channel is used to keep track of the currently
// opened Secure Channel Session and SecurityDomain is a handle to this
// application's associated Security Domain.
private byte channel;
private ProviderSecurityDomain SecurityDomain;
// Application specific key.
private static DESKey appletKey;
// Instance of the DES cipher object.
private static Cipher DESInstance;
/* Applet constructor
*
The constructor for the applet would typically be where objects to be
*
used by the applet would be instantiated but not necessarily populated.
*
For the purpose of this example code, the only function of the constructor
*
is to register itself with the instance AID defined by the off-card
*
entity.
*
@ Parameters
*
buffer :- buffer containing at least the instance AID and application
*
privileges.
*
offset :- offset within the buffer pointing to the beginning of the
*
instance AID length.
*
length :- length of the install parameters within the buffer.
**/
protected Sample(byte[] buffer, short offset, byte length) {
// Determine the length of the instance AID.
byte instanceLength = (byte) buffer[offset];
// Locate the install privileges.
byte appletPrivileges = (byte) buffer[
(short) (offset+1+instanceLength+1)];
// Ensure that the applet has PIN Change permission.
if ( appletPrivileges != PIN_Change_Privilege )
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
appletKey
DESInstance = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD,false);
}
/* Install method
*
As defined in the Java Card specifications and invoked by the JCRE on receipt
*
of an INSTALL [for instal]l command as defined in the GlobalPlatform
*
specifications.
*
Parameters
*
buffer :- buffer containing at least the length and values of the
*
following: instance AID, application privileges and
*
application specific parameters
*
offset :- offset within the buffer pointing to the beginning of the
*
install parameters i.e. instance AID length.
*
length :- length of the install parameters within the buffer.
*
Note that this example applet does not utilize application specific parameters.
**/
public static void install(byte[] buffer, short offset, byte length) {
// Applet constructor
new Sample(buffer, offset, length);
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
52
/*
Select method
*
As defined in the Java Card specifications and invoked by the JCRE on receipt
*
of a SELECT command indicating this applet's instance.
*
Please note that it is advised that, for Global Platform, minimal code, if any,
*
be contained in this method and that for no reason should this method ever fail
*
or return false rather than true.
**/
public boolean select() {
// Retrieve the handle of the Security Domain associated with this applet.
SecurityDomain = OPSystem.getSecurityDomain();
}
/* Deselect method
* calling closeSecureChannel() will ensure that if a Secure Channel Session
* has been established, it will not be available to another application.
* If a Secure Channel Session has not been established, this call will have no
* effect
**/
public void deselect() {
SecurityDomain.closeSecureChannel(channel);
}
/* Process method
*
As defined in the Java Card specifications and invoked by the JCRE on
*
receipt of a command intended for the applet. The applet is responsible
*
for processing or dispatching each command.
*
Parameters
*
apdu :- the apdu buffer.
**/
public void process( APDU apdu ) {
// Generally commands are dispatched within an application according to
// their class and instruction bytes. Secure messaging is checked by
// individual methods.
byte[] buffer = apdu.getBuffer();
byte cla = (byte) (buffer[ ISO7816.OFFSET_CLA ] & (byte) SM_MASK);
byte ins = buffer[ ISO7816.OFFSET_INS ];
// ISO class
if( cla == ISO7816.CLA_ISO7816 ){
switch ( buffer[ISO7816.OFFSET_INS] ) {
// SELECT Command
case (byte) ISO7816.INS_SELECT: processSelect( apdu );
break;
// PRESENT PIN command
case (byte) INS_VERIFY: presentPIN( apdu );
break;
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
} /* end switch */
return;
}
// Proprietary class commands
if( cla == CLA_Proprietary ){
switch ( buffer[ISO7816.OFFSET_INS] ) {
// INITIALIZE UPDATE command
case (byte) INS_INITIALIZE_UPDATE: initializeUpdate( apdu );
break;
// EXTERNAL AUTHENTICATE command
case (byte) ISO7816.INS_EXTERNAL_AUTHENTICATE: externalAuthenticate( apdu );
break;
// PUT KEY command
case (byte) INS_PUT_KEY: personalize( apdu );
break;
Copyright 2002 GlobalPlatform Inc. All Rights Reserved.
The technology provided or described herein is subject to updates, revisions, and extensions by GlobalPlatform. Use of
this information is governed by the GlobalPlatform license agreement and any use inconsistent with that agreement is
strictly prohibited.
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
// CHANGE PIN command
case (byte) INS_CHANGE_PIN: changePIN( apdu );
break;
// GET STATUS command
case (byte) INS_GET_STATUS: getStatus( apdu );
break;
default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
} /* end switch */
return;
}
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
/* processSelect method
*
Method to handle the SELECT command.
*
Parameters
*
apdu :- the apdu buffer.
**/
void processSelect( APDU apdu ) {
// As the JCRE dispatches SELECT commands which cannot be accessed through the
// registry to the currently selected applet, the applet must insure it is being
// selected prior to responding.
if( !selectingApplet() ) {
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}
// Even though the command message has already been received by the JCRE, for
// consistency a pseudo receive is performed.
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
// Retrieve the complete AID of the selected applet and build the Select
// response string.
short offset = ISO7816.OFFSET_CDATA;
short AIDLength =
JCSystem.getAID().getBytes(buffer, (short)(offset+4));
buffer[offset] = (byte) FCI_TEMPLATEemplate;
buffer[offset+1] = (byte)(4+AIDLength);
buffer[offset+2] = (byte) AID_Tag;
buffer[offset+3] = (byte) AIDLength;
buffer[offset+4+AIDLength] = (byte) Proprietary_Data_Template;
buffer[offset+4+AIDLength+1] = (byte) 0x00;
apdu.setOutgoingAndSend( (short) ISO7816.OFFSET_CDATA, (short) (6+AIDLength) );
/* initializeUpdate method
*
Method to handle the INITIALIZE UPDATE command.
*
The processing for this command is performed by the Security Domain
*
associated with the application.
*
Errors are managed and output by the Security Domain.
*
Parameters
*
apdu :- the apdu buffer.
**/
void initializeUpdate ( APDU apdu ) {
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
// The openSecureChannel method expects to receive the APDU as defined in the
// GlobalPlatform specifications.
// The channel number returned must be used for all subsequent invocations of
// Security Domain methods.
channel = SecurityDomain.openSecureChannel( apdu );
// The prepared response message is placed back in the buffer by the Security
// Domain in position 5. The length to be output is found in position 4.
short responseLength = buffer[ISO7816.OFFSET_LC];
apdu.setOutgoingAndSend( (short) ISO7816.OFFSET_CDATA, responseLength );
53
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
54
/* externalAuthenticate method
*
Method to handle the EXTERNAL AUTHENTICATE command.
*
The processing for this command is performed by the Security Domain
*
associated with the application.
*
Errors are managed and output by the Security Domain.
*
Parameters
*
apdu :- the apdu buffer.
**/
void externalAuthenticate ( APDU apdu ) {
apdu.setIncomingAndReceive();
byte[] buffer = apdu.getBuffer();
/* personalize method
*
Method to handle the personalization (PUT KEY) command.
*
The personalization command requires secure messaging and contains
*
one single length key data object formatted according to the
*
GlobalPlatform specifications.
*
Parameters
*
apdu :- the apdu buffer.
**/
void personalize( APDU apdu ) {
// The applet checks its own state to insure it is not already personalized.
if( OPSystem.getCardContentState() != OPSystem.APPLET_SELECTABLE )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
// The applet expects some kind of secure messaging i.e. MAC or MAC and encryption.
byte[] buffer = apdu.getBuffer();
if( buffer[ ISO7816.OFFSET_CLA ] != CLA_Proprietary_Secured )
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
// The personalization data is retrieved and the command is unwrapped by the
// Security Domain.
// Errors in the unwrapping process are managed and output by the Security Domain.
apdu.setIncomingAndReceive();
SecurityDomain.unwrap(channel, apdu);
// The command is now in an unwrapped state and the key can now be decrypted
// and verified by the Security Domain. In this case the applet is responsible
// for determining the action taken if the key cannot be verified by the Security
// Domain.
// This example sets the key as the applet key if the method returns true and
// throws an error if the method returns false.
if( SecurityDomain.decryptVerifyKey(channel,apdu, (short)(ISO7816.OFFSET_CDATA+1)) )
{
appletKey.setKey(buffer, (short)(ISO7816.OFFSET_CDATA+3));
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
55
/* getStatus method
*
Method to handle the Get Status command.
*
The Get Status command may or may not include secure messaging and returns
*
the status of the application to the off-card entity.
*
Parameters
*
apdu :- the apdu buffer.
**/
void getStatus( APDU apdu ) {
byte[] buffer = apdu.getBuffer();
// Only if the command includes secure messaging will it contain a command
// message i.e. a MAC. In which case the command message must be retrieved
// and the command unwrapped.
// Errors in the unwrapping process are managed and output by the
// Security Domain.
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_Proprietary_Secured ){
apdu.setIncomingAndReceive();
SecurityDomain.unwrap(channel, apdu);
}
// The application Life Cycle State is retrieved and output to the external entity.
buffer[ISO7816.OFFSET_CDATA] = OPSystem.getCardContentState();
apdu.setOutgoingAndSend( (short) ISO7816.OFFSET_CDATA, (short) 1 );
/* presentPIN method
*
Method to handle the present PIN command.
*
The present PIN command checks that the PIN presented by the external entity
*
to the card is valid. As this is the global PIN, the applet assumes that
*
the PIN has been previously populated.
*
Parameters
*
apdu :- the apdu buffer.
**/
void presentPIN( APDU apdu ) {
// PIN presentation can only occur when the application is in a personalized state.
if( OPSystem.getCardContentState() != OPSystem.APPLET_PERSONALIZED )
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
// If the PIN retry limit has been reached, an appropriate error, indicating that
// the PIN is blocked, is thrown.
if( OPSystem.getTriesRemaining() == 0 )
ISOException.throwIt(Util.makeShort( (byte) 0x69, (byte) 0x83));
// Retrieve the PIN data and unwrap the command if secure messaging is present.
byte[] buffer = apdu.getBuffer();
apdu.setIncomingAndReceive();
if( buffer[ ISO7816.OFFSET_CLA ] == CLA_ISO7816_Secured )
SecurityDomain.unwrap(channel, apdu);
// The applet assumes that the PIN formating required by the verifyPIN() method
// has been applied by the off-card entity.
if( OPSystem.verifyPin( apdu, ISO7816.OFFSET_CDATA )){
PINPresented = true;
// If PIN presentation failed, an appropriate error indicating how many
// opportunities remain to present the correct PIN will be thrown.
} else {
PINPresented = false;
byte triesRemaining = (byte) (OPSystem.getTriesRemaining() | (byte) 0xc0 );
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
56
/* changePIN method
*
Method to handle the change PIN command.
*
The change PIN command allows the global PIN to be changed if the correct
*
PIN has been previously presented.
*
Parameters
*
apdu :- the apdu buffer.
**/
void changePIN( APDU apdu ) {
} // end applet
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
57
58
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
59
/******************************************************************/
/*
cmd_STOREDATA
*
applet personalization code:
*
personalize the Password
*/
private void cmd_STOREDATA (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bReadBytes = (byte)(apdu.setIncomingAndReceive());
if ((GPSystem.getCardContentState()) == GPSystem.APPLICATION_SELECTABLE) {
// the applet has not been personalized yet, perform regular personalization
// check for card life cycle
if ((GPSystem.getCardState()) == GPSystem.CARD_SECURED ) {
// it's post-issuance
// this applet does not implement support for this situation
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} else {
AppletPW.update(buffer, ISO7816.OFFSET_CDATA,
(byte)buffer[ISO7816.OFFSET_LC]);
} /* end if */
} else {
// the applet is personalized, but a perso command is received
// this applet does not implement support for this situation.
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} /* end if */
} /* end method */
/******************************************************************/
/*
cmd_VERIFY
*
verification of the applet Password for card holder verification
*/
private void cmd_VERIFY (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bAppletLifeCycle = GPSystem.getCardContentState();
byte bReadBytes = (byte)(apdu.setIncomingAndReceive());
// short sStatusWord = SW_INVALID_PW;
// this command is only executed in CARD_SECURED,
check_CARD_SECURED();
if ((AppletPW.check(buffer, ISO7816.OFFSET_CDATA, (byte)buffer[ISO7816.OFFSET_LC]))
== false) {
// Are there any Password verification tries left?
if ((AppletPW.getTriesRemaining()) == (byte) 1) {
// if there is one try left, block application
// now there is only one more chance!
// Otherwise Password will be blocked
GPSystem.setCardContentState(APPLET_BLOCKED);
} /* end if */
ISOException.throwIt((short)(SW_INVALID_PW +
(short)(AppletPW.getTriesRemaining())));
} /* end if */
} /* end method */
/******************************************************************/
/*
cmd_COLLECT
*
collect more loyalty points
*/
private void cmd_COLLECT (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bReadbytes = (byte)(apdu.setIncomingAndReceive());
/* loyalty collection is only done when:
*
(a) card life cycle is post-issuance
*
(b) applet is personalized,
*
(c) card holder verification was successfull */
check_CARD_SECURED();
check_PERSONALIZED();
check_PWVALIDATED();
sLoyaltyPoints = (short) (sLoyaltyPoints + buffer[ISO7816.OFFSET_CDATA]);
} // end method
60
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
/******************************************************************/
/*
cmd_REDEEM
*
Redeem some of the loyalty points
*/
private void cmd_REDEEM (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bReadbytes = (byte)(apdu.setIncomingAndReceive());
byte bRedeemAmount = buffer[ISO7816.OFFSET_CDATA];
/* loyalty redeeming is only done when:
*
(a) card life cycle is post-issuance
*
(b) applet is personalized,
*
(c) card holder verification was successfull */
check_CARD_SECURED();
check_PERSONALIZED();
check_PWVALIDATED();
if ((short)bRedeemAmount > sLoyaltyPoints) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} else {
sLoyaltyPoints = (short) (sLoyaltyPoints - (short)bRedeemAmount);
} // end if
Util.setShort(buffer, (short)0, sLoyaltyPoints);
apdu.setOutgoingAndSend((short)0, (short)2);
} // end method
/******************************************************************/
private void check_PERSONALIZED () {
if (GPSystem.getCardContentState() != APPLET_PERSONALIZED) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} /* end if */
} /* end method */
/******************************************************************/
private void check_PWVALIDATED () {
if (AppletPW.isValidated() == false) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} // end if
} // end method
/******************************************************************/
/*
check_CARD_SECURED */
private void check_CARD_SECURED () {
if (GPSystem.getCardState() != GPSystem.CARD_SECURED) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} // end if
} // end method
} // end applet
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
61
62
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
63
/******************************************************************/
/*
cmd_STOREDATA
*
applet personalization code:
*
personalize the Password
*/
private void cmd_STOREDATA (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bReadBytes = (byte)(apdu.setIncomingAndReceive());
if ((OPSystem.getCardContentState()) == OPSystem.APPLET_SELECTABLE) {
// the applet has not been personalized yet, perform regular personalization
// check for card life cycle
if ((OPSystem.getCardManagerState()) == OPSystem.CARD_SECURED ) {
// it's post-issuance
// this applet does not implement support for this situation
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} else {
AppletPW.update(buffer, ISO7816.OFFSET_CDATA,
(byte)buffer[ISO7816.OFFSET_LC]);
} /* end if */
} else {
// the applet is personalized, but a perso command is received
// this applet does not implement support for this situation.
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} /* end if */
} /* end method */
/******************************************************************/
/*
cmd_VERIFY
*
verification of the applet Password for card holder verification
*/
private void cmd_VERIFY (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bAppletLifeCycle = OPSystem.getCardContentState();
byte bReadBytes = (byte)(apdu.setIncomingAndReceive());
// this command is only executed in CARD_SECURED,
check_CARD_SECURED();
if ((AppletPW.check(buffer, ISO7816.OFFSET_CDATA, (byte)buffer[ISO7816.OFFSET_LC]))
== false) {
// Are there any Password verification tries left?
if ((AppletPW.getTriesRemaining()) == (byte) 1) {
// if there is one try left, block application
// now there is only one more chance!
// Otherwise Password will be blocked
OPSystem.setCardContentState(OPSystem.APPLET_BLOCKED);
} /* end if */
ISOException.throwIt((short)(SW_INVALID_PW +
(short)(AppletPW.getTriesRemaining())));
} /* end if */
} /* end method */
/******************************************************************/
/*
cmd_COLLECT
*
collect more loyalty points
*/
private void cmd_COLLECT (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bReadbytes = (byte)(apdu.setIncomingAndReceive());
/* loyalty collection is only done when:
*
(a) card life cycle is post-issuance
*
(b) applet is personalized,
*
(c) card holder verification was successfull */
check_CARD_SECURED();
check_PERSONALIZED();
check_PWVALIDATED();
sLoyaltyPoints = (short) (sLoyaltyPoints + buffer[ISO7816.OFFSET_CDATA]);
} // end method
64
December 2002
Guidelines for Developing Java Card Applications on GlobalPlatform 2.1 Cards
Version 1.0
/******************************************************************/
/*
cmd_REDEEM
*
Redeem some of the loyalty points
*/
private void cmd_REDEEM (APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte bReadbytes = (byte)(apdu.setIncomingAndReceive());
byte bRedeemAmount = buffer[ISO7816.OFFSET_CDATA];
/* loyalty redeeming is only done when:
*
(a) card life cycle is post-issuance
*
(b) applet is personalized,
*
(c) card holder verification was successfull */
check_CARD_SECURED();
check_PERSONALIZED();
check_PWVALIDATED();
if ((short)bRedeemAmount > sLoyaltyPoints) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} else {
sLoyaltyPoints = (short) (sLoyaltyPoints - (short)bRedeemAmount);
} // end if
Util.setShort(buffer, (short)0, sLoyaltyPoints);
apdu.setOutgoingAndSend((short)0, (short)2);
} // end method
/******************************************************************/
private void check_PERSONALIZED () {
if (OPSystem.getCardContentState() != OPSystem.APPLET_PERSONALIZED) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} /* end if */
} /* end method */
/******************************************************************/
private void check_PWVALIDATED () {
if (AppletPW.isValidated() == false) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} // end if
} // end method
/******************************************************************/
/*
check_CARD_SECURED */
private void check_CARD_SECURED () {
if (OPSystem.getCardManagerState() != OPSystem.CARD_SECURED) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
} // end if
} // end method
} // end applet
Filename:
GP_Guidelines_for_Developing_Apps_on_GP_Cards_v1.0a
Directory:
C:\Documents and Settings\kekichef\My
Documents\Data\GlobalPlatform\CSD WG
Template:
C:\Documents and Settings\kekichef\Application
Data\Microsoft\Templates\Normal.dot
Title:
GP Guidelines for developing Applications on GP cards
Subject:
GP Application development
Author:
Mike Berg
Keywords:
Comments:
Creation Date:
12/17/2002 1:07 PM
Change Number:
4
Last Saved On:
12/18/2002 3:58 PM
Last Saved By:
Kekichef
Total Editing Time:
7 Minutes
Last Printed On:
12/18/2002 3:59 PM
As of Last Complete Printing
Number of Pages: 64
Number of Words: 18,912 (approx.)
Number of Characters:
107,800 (approx.)