Calypso application

Overview

Keyple API was designed to support an extension system. On top of Keyple Core, APIs can be developed to extend Keyple features. For example, Calypso Network Association provides Keyple Calypso Extension.

The use of Keyple Calypso Extension open the ability to operate commands with a Calypso Portable Object and to manage a secure Calypso transaction seamlessly. It completely hides the details of the APDU commands that are sent to POs and SAMs, which are usually tedious operations.

The diagram below shows the role of the Keyple Calypso Extension components in the software layers for a standalone application :

Before you start

  1. In pre-requisite, have knowledge of the standard Calypso.
  2. Read the common concepts page and become familiar with the basic concepts on which Keyple is based.
  3. Any implementation of a Keyple application starts with the implementation of Keyple Core, please study the workflow proposed in Standalone application guide.
  4. Read chapter Concepts to understand the main terms and concepts of the Keyple Calypso Extension API.
  5. Explore the Keyple Calypso API to discover all the possibilities offered by Keyple Calypso Extension.
  6. Take inspiration from the examples.
  7. Follow the explanations given in the Build your first app section to configure your environment.
  8. Using the Java components or C++ components pages, import Keyple Core into your project.
  9. Using the Java components or C++ components pages, import Keyple Calypso Extension into your project.
  10. Start playing with Keyple.

Concepts

Here are the main concepts to keep in mind before continuing to read this developer guide :

Calypso PO

Concentrates all known information about the Personal Object being processed. Accessible information are

  • The application identification fields (revision/version, class, DF name, serial number, ATR, issuer)
  • The indication of the presence of optional features (Stored Value, PIN, Rev3.2 mode, ratification management)
  • The management information of the session modifications buffer
  • The invalidation status
  • The files, counters, SV data read or modified during the execution of the processes defined by PoTransaction

The Calypso PO fields are first populated from the CardSelectionResponse obtained through the PO selection process then each time a PoTransaction “process” method is invoked.

    ...
    //Retrieve PO's informations
    String atr = calypsoPo.getAtr()
    byte[] applicationSerial+Number = calypsoPo.getApplicationSerialNumber()
    //SFI_EventLog = 0x08
    ElementaryFile efEventLog = calypsoPo.getFileBySfi(SFI_EventLog);
    //SFI_EnvironmentAndHolder = 0x07
    ElementaryFile efEnvironmentAndHolder =calypsoPo.getFileBySfi(SFI_EnvironmentAndHolder);
    ...

ElementaryFile

Object containing the description of a Calypso Elementary File. Can be retrieved from Calypso PO using its SFI.

    ...
    ElementaryFile efEventLog = calypsoPo.getFileBySfi(SFI_EventLog);
    //Read data content of sevent log elemenatary file
    String eventLog = ByteArrayUtil.toHex(efEventLog.getData().getContent());
    ...

Calypso SAM

Concentrates all the informations we know about the SAM currently selected. Accessible informations are:

  • The Sam Revision
  • The Serial number
  • The Platform identifier
  • The Application Type
  • The Application SubType
  • The Software Issuer identifier
  • The Software Version number
  • The Software Revision number

Calypso SAM fields are populated by analysis of the ATR within a CardSelectionResponse obtained through the SAM selection process.

    ...
    byte[] serialNumber = calypsoSam.getSerialNumber()
    ...

PoSecuritySettings

Concentrate the security settings involved in Calypso Secure Sessions:

  • A reference to the SAM resource
  • The default KIF
  • The default KVC
  • The default Key Record Number
  • The modification mode
  • The ratification mode
  • The pin transmission mode
  • The default Pin Ciphering Key
  • The SV Get Log Read mode
  • The SV Negative balance mode

The fields are populated with default values when the object is instantiated but can be customized to adjust the settings to the application needs.

    ...
    poSecuritySettings.getSessionModificationMode()
    ...

Secure session settings can be finely tuned with PoSecuritySettings and a set of enums provided by Keyple:

Modification mode

Indicates whether the secure session can be closed and reopened to manage the limitation of the PO buffer memory (session modifications buffer).

ModificationModeDescription
ATOMICThe secure session is atomic.
MULTIPLESeveral secure sessions will be chained (to manage the writing of large amounts of data).
    ...
   PoSecuritySettings poSecuritySettings =
       new PoSecuritySettings.PoSecuritySettingsBuilder(samResource)
           .svGetLogReadMode(SvSettings.LogRead.ALL)
           .build();
    ...

Ratification mode

The ratification mode defines the behavior of processClosing regarding the ratification process.

RatificationModeDescription
CLOSE_RATIFIEDClose session with ratification.
CLOSE_NOT_RATIFIEDClose session without ratification
    ...
   PoSecuritySettings poSecuritySettings =
       new PoSecuritySettings.PoSecuritySettingsBuilder(samResource)
           .ratificationMode(RatificationMode.CLOSE_RATIFIED)
           .build();
    ...

Pin Transmission Mode

Defines the PIN transmission modes: plain or encrypted.

PinTransmissionMode
PLAIN
ENCRYPTED

SV Log Read mode

Specifies whether only one or both SV logs (debit and load) should be read.

LogRead
SINGLE
ALL

SV Negative balance mode

Specifies whether POs with a negative SV balance should be accepted.

NegativeBalance
FORBIDDEN
AUTHORIZED

Basic Operations

PoSelection

This service provides the means to define a selection case targeting a particular PO (in the ISO 7816-4 sense) with the possibility to collect additional information about the PO before a transaction.

It integrates with the Keyple Core Card Selection service to manage the specific features of Calypso POs:

  • Sends optional read and/or select commands to the POs right after the initial card selection.
  • Produces a CalypsoPO object from the CardSelectionResponse. The object is filled with the PO identification data from the FCI and the possible responses to additional APDU commands executed after the selection.
    ...
    // Prepare a Calypso PO selection
    CardSelectionsService cardSelectionsService = new CardSelectionsService();

    // Setting of an AID based selection of a Calypso REV3 PO
    // Select the first application matching the selection AID whatever the card communication
    // protocol keep the logical channel open after the selection

    // Calypso selection: configures a PoSelection with all the desired attributes to
    // make the selection and read additional information afterwards
    PoSelection poSelection =
        new PoSelection(
            PoSelector.builder()
                .cardProtocol(ContactlessCardCommonProtocols.ISO_14443_4.name())
                .aidSelector(
                    CardSelector.AidSelector.builder().aidToSelect(CalypsoClassicInfo.AID).build())
                .invalidatedPo(PoSelector.InvalidatedPo.REJECT)
                .build());

    // Prepare the reading order.
    poSelection.prepareReadRecordFile(
        CalypsoClassicInfo.SFI_EnvironmentAndHolder, CalypsoClassicInfo.RECORD_NUMBER_1);

    // Add the selection case to the current selection (we could have added other cases
    // here)
    cardSelectionsService.prepareSelection(poSelection);
    CalypsoPo calypsoPo = (CalypsoPo) cardSelectionsService.processExplicitSelections(poReader).getActiveSmartCard();
    ...

SamSelection

This service provides the means to define a selection case targeting a Calypso SAM.

It integrates with the Keyple Core Card Selection service to manage the specific features of Calypso SAMs:

  • optionally executes an unlock command during the selection process.
  • provides an instance of Calypso SAM.
    ...
    CardSelectionsService samSelection = new CardSelectionsService();

    //Sam selection parameters
    SamSelector samSelector = SamSelector.builder().samRevision(SamRevision.C1).serialNumber(".*").build();
    samSelection.prepareSelection(new SamSelection(samSelector));

    //Sam reader retrieved from registered plugin
    CardSelectionsResult cardSelectionsResult = samSelection.processExplicitSelections(samReader);
    if (!cardSelectionsResult.hasActiveSelection()) {
      throw new IllegalStateException("Unable to open a logical channel for SAM!");
    }

    //Cast selected card to CalypsoSam
    CalypsoSam calypsoSam = (CalypsoSam) cardSelectionsResult.getActiveSmartCard();
    ...

PoTransaction

Service providing high-level API to manage transactions with a Calypso PO. The tied CalypsoPO Object is kept and updated at each step of using this service.

This service workflow is composed of two steps:

  • Prepares the commands to be sent to the PO; several command preparations can be stacked (no communication neither with the PO nor with the SAM).
  • Process the prepared commands. Performs all necessary communications with the PO and/or the SAM to carry out the previously prepared operations. CalypsoPo is updated accordingly.

Note:

  • Regarding of commands, the presence of SAM is mandatory or not (mandatory when a Calypso Secure Session is open).
  • Pay attention to the number of commands affecting the session modifications buffer, see the ModificationMode setting.
    ...
    // CardResource allow management of specific card.
    // In this example a SAM is available 
    CardResource<CalypsoPo> poResource = new CardResource<CalypsoPo>(poReader, calypsoPo);
    CardResource<CalypsoSam> samResource = new CardResource<CalypsoPo>(samReader, calypsoSam);
    
    // Configure Security settings
    // Both Reload and Debit SV logs are requested
    PoSecuritySettings poSecuritySettings =
        new PoSecuritySettings.PoSecuritySettingsBuilder(samResource)
            .svGetLogReadMode(SvSettings.LogRead.ALL)
            .build();

    PoTransaction poTransaction = new PoTransaction(poResource, poSecuritySettings);

    // Read the EventLog file at record 1 within the Session Opening
    poTransaction.prepareReadRecordFile(CalypsoClassicInfo.SFI_EventLog, CalypsoClassicInfo.RECORD_NUMBER_1);

    // Open a secure session (DEBIT level) and execute the prepared command
    poTransaction.processOpening(PoTransaction.SessionSetting.AccessLevel.SESSION_LVL_DEBIT);

    // Get and display the EventLog data
    ElementaryFile efEventLog = calypsoPo.getFileBySfi(CalypsoClassicInfo.SFI_EventLog);

    // Example of data parsing
    String eventLog = ByteArrayUtil.toHex(efEventLog.getData().getContent());

    // Prepare a SV Debit (this command could also have been placed before processOpening
    // since it is not followed by any other command)
    poTransaction.prepareSvGet(SvSettings.Operation.DEBIT, SvSettings.Action.DO);

    // Execute the prepared command
    poTransaction.processPoCommands();

    //Get updated sv balance
    int svBalance = calypsoPo.getSvBalance()

    //Get the updated SV last transaction number
    int svLastTNum = calypsoPo.getSvLastTNum()
    ...

Secure Session Access level

PoTransaction.processOpening() allows to open a Calypso Secure Session. If commands have been prepared previously, they will be executed.

Keyple provides an enums to easily configure the Secure Session AccessLevel:

AccessLevelDescription
SESSION_LVL_PERSOSession Access Level used for personalization purposes.
SESSION_LVL_LOADSession Access Level used for reloading purposes.
SESSION_LVL_DEBITSession Access Level used for validating and debiting purposes.

Transaction flow and Calypso Secure Session management

PoTransaction allows you to process a Calypso Secure session in different ways. These are difficult to describe all in detail but here is an example from which other variants can be obtained.

A typical Calypso PO transaction flow, for example for ticket validation, could be :

  • Execute the selection of a Calypso PO and retrieves the contents of the environment file at the same time.
  • Open a secure session and get the contract list
  • Get the contract and associated counter
  • Decrease the counter, append a new event log
  • Close the secure session

Translated into Keyple Calypso operations, the entire transaction would include the following steps (simplified syntax):

  • poSelection = new PoSelection(CARD_IAD)
  • poSelection.prepareReadRecordFile(ENVIRONMENT_SFI)
  • process the poSelection (either explicitly or by default, see the standalone application) guide
  • retrieve CalypsoPo, check its content (environment data)
  • poTransaction = new PoTransaction(calypsoPo)
  • poTransaction.prepareReadRecordFile(CONTRACT_LIST_SFI)
  • poTransaction.processOpening(DEBIT)
  • check CalypsoPo content (contract list), decide which contract/counter to read
  • poTransaction.prepareReadRecordFile(CONTRACT_n)
  • poTransaction.prepareReadRecordFile(COUNTER_n)
  • poTransaction.processPoCommands()
  • check CalypsoPo content (contract/counter), decide action (decrease counter, append event log)
  • poTransaction.prepareDecrease(COUNTER_n, X)
  • poTransaction.prepareAppendRecord(EVENT, event_data
  • poTransaction.prepareReleaseChannel()
  • poTransaction.processClosing()

Examples

Detailed use case examples can be seen here:

Previous
Next