Sample Code
Setup
The setup consists in initializing the structure of the system, i.e. the message broker
and all the services to be used. To do so, you shall use switstack moka's manager
that exposes an API to allocate memory space and register the functional components.
Service | Description | Release Status |
---|---|---|
SERVICE_TYPE_CPA_1 | Deprecated. | N/A. |
SERVICE_TYPE_CPA_MASTERCARD | EMVCo Book C-2 implementation. | Qualification in progress. |
SERVICE_TYPE_CPA_VISA | Visa specifications implementation. | Qualification in progress. |
SERVICE_TYPE_CPA_AMEX | American Express specifications implementations. | Qualification in progress. |
SERVICE_TYPE_CPA_5 | JCB specifications implementations. | To be planned. |
SERVICE_TYPE_CPA_6 | Discover specifications implementations. | Development in progress. |
SERVICE_TYPE_CPA_7 | CUP-QuickPass Overseas specifications implementations. | To be planned. |
SERVICE_TYPE_CPA_8 | EMVCo Book C-8 implementation. | To be planned. |
SERVICE_TYPE_CPA_9 | RFU. | N/A. |
SERVICE_TYPE_CPA_10 | RFU. | N/A. |
SERVICE_TYPE_CPA_11 | RFU. | N/A. |
SERVICE_TYPE_CPA_12 | RFU. | N/A. |
SERVICE_TYPE_CPA_13 | RFU. | N/A. |
SERVICE_TYPE_CPA_14 | RFU. | N/A. |
SERVICE_TYPE_CPA_15 | RFU. | N/A. |
SERVICE_TYPE_ENTRY_POINT | EMVCo Books A/B implementation. | Available. |
SERVICE_TYPE_READER | Card coupling, and SRED module. | Available. |
SERVICE_TYPE_PINPAD | PIN capture and PIN block encipherment. | Roadmaped. |
SERVICE_TYPE_HSM | CAPK storage. | Available. |
SERVICE_TYPE_DISPLAY | Output. | Available. |
SERVICE_TYPE_CARD | Card simulation. | Available. |
SERVICE_TYPE_LOGGER | Machine readable log generator. | Available. |
SERVICE_TYPE_GLASE | Generic EMV Level 2 encapsulation. | Available. |
SERVICE_TYPE_APPLICATION | Any application used to inteface switstack moka to external an software system. | To be planned. |
Info
All kernels are qualified against payment networks test plans and automated test plans are made available for faster qualification. EMVCo certifications are not targeted, excepted for EMVCo Book C-8.
So, the programmatic sequence should be as followed:
Store a list of services
Each entry of this table corresponds to the service's entry point address, i.e. the proxy.
Instantiate message broker
Allocate memory to store EMV tags
static uint8_t g_entry_point_storage[2500] = ""; // Contactless comnbinations.
static uint8_t g_tags_storage[5000] = ""; // EMV transactions.
Set up services
uint16_t
moka_setup(void)
{
srv_mng_reset();
/* Setup services manager */
srv_mng_initialize_services_manager(&g_my_message_broker, my_routing_table, NUMBER_OF_SERVICES);
srv_mng_set_services_data_storage(
g_tags_storage,
sizeof(g_tags_storage),
g_entry_point_storage,
sizeof(g_entry_point_storage));
/* Add services */
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_CARD);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_READER);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_ENTRY_POINT);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_CPA_MASTERCARD);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_GLASE);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_LOGGER);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_HSM);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_DISPLAY);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_CPA_VISA);
srv_mng_add_service(&g_my_message_broker, SERVICE_TYPE_CPA_AMEX);
/* Start message broker */
srv_mng_setup_services();
return MOKA_OK;
}
Note
SERVICE_TYPE_CARD is used to simualte cards and enable EMV software-defined testing.
Configuration`
The configuration consists in completing the setup for specific services that require internal parameters to work properly. Like the setup, the configuration is performed only once ahead of the cycle of transactions. There are two ways to configure a service:
- Either use GENERIC_SERVICE_SET_PARAMETERS and send a TLV including a set of parameters;
- Either use a functional service that depends on the service;
Info
Use service's data models to know what parameters are available for configurations (sse Appendix).
uint8_t key_data[BUFFER_SIZE_512] = "";
uint16_t key_data_length = 0;
uint8_t revocation_data[BUFFER_SIZE_64] = "";
uint16_t revocation_data_length = 0;
uint8_t config_data[BUFFER_SIZE_512] = "";
uint16_t config_data_length = 0;
// All data buffer shall be initialized with a TLV structure corresponding to moka's data model
glase.flush_ca_keys();
glase.add_ca_key(key_data, key_data_length);
glase.add_revocated_certificate(revocation_data, revocation_data_length);
// Important: the reference transaction type shall be set ahead of this call as soon as it is known
glase.add_combination(config_data, config_data_length);
Pre-conditions
This step consists in cleaning-up the kernels, and other services. This shall be performed before aech new transaction.
/* Prepare sred reader */
srv_mng_initialize_service(SERVICE_TYPE_READER);
/* Prepare mastercard kernel */
srv_mng_initialize_service(SERVICE_TYPE_CPA_MASTERCARD);
/* Prepare visa kernel */
srv_mng_initialize_service(SERVICE_TYPE_CPA_VISA);
/* Prepare amex kernel */
srv_mng_initialize_service(SERVICE_TYPE_CPA_AMEX);
Info
Additional calls to GENERIC_SERVICE_SET_PARAMETERS may be peformed depending on the service to use. But concerning the kernels, they are mainly set from the combinations that are selected by the entry point.
Initiate Card Processing
Pre-processing
This step consists in pre-processing contactless combinations, i.e. performing a start A.
uint8_t buffer[BUFFER_SIZE_256] = "";
uint16_t buffer_length = sizeof(buffer);
// trd is a TLV containing amount, other amount, currency code, etc...
// buffer indicates number of allowed combinations
glase.pre_processing(trd, trd, buffer, &buffer_length);
Card polling
This step consists in detecting a card, i.e. performing a start B.
uint16_t moka_error = MOKA_OK;
uint8_t detected_interface = HAL_NO_CARD_INTERFACE;
glase.protocol_activation(&detected_interfaces);
Application selection
This step consists in selecting an EMV application, i.e. performing a start C.
uint8_t buffer[BUFFER_SIZE_256] = "";
uint16_t buffer_length;
hal_os_memset(buffer, 0x00, sizeof(buffer));
buffer_length = sizeof(buffer);
glase.combination_selection(buffer, &buffer_length);
// Fetch some tags corresponding to the selected candidate
hal_os_memset(buffer, 0x00, sizeof(buffer));
buffer_length = sizeof(buffer);
glase.get_tag_from_candidate((const uint8_t*)"\x9F\x06", 2, buffer, &buffer_length);
hal_os_memset(buffer, 0x00, sizeof(buffer));
buffer_length = sizeof(buffer);
glase.get_tag_from_candidate((const uint8_t*)"\x87", 1, buffer, &buffer_length);
Warning
Current version doesn't allow to get tags from a specific candidate within the entry point's candidate list. Here, the APi simply fetches 0x9F06 and 0x87 tags from the candidate implicity selected during start C prcoess (having the highest priority). This feature is not required by EMVCo and payment networks but it provides a certain level of flexibility for particualr regional markets. This feature will be included in the next version.
Kernel activation
This step consists in activating the kernel that corresponds to the EMV application selected during start C process, i.e. performing a start D.
uint8_t buffer[BUFFER_SIZE_256] = "";
uint16_t buffer_length;
hal_os_memset(buffer, 0x00, sizeof(buffer));
buffer_length = sizeof(buffer);
glase.kernel_activation(buffer, buffer_length);
Complete Card Processing
This step is optional and corresponds to a second presentment or long tap. Once the system goes lines, the issuer responses may require to communicate again with the card. For example, issuer script management is a typical use case. This option is not supported by all kernels.
Post-conditions
This step consists in analysing the outcome of a transaction. It is required:
- After kernel activation, and
- After completion;
In both situations, the application level need to get some tags to take decisions, and prepare online messahe or even capture information for batches. All tags can read fron a single call using the following API:
uint8_t buffer[BUFFER_SIZE_256] = "";
uint16_t buffer_length;
glase.get_tag((const uint8_t*)"\x9F\x33\x5A", 3, buffer, buffer_length);
Info
With switstack moka
, all EMV data objects are managed as tags including the signals. Use outcome parameter set signal to get the final outcome, for example.