Skip to content

Switstack moka Terminal (SmT)

Switstack monitoring terminal is a tool that comes with moka to perform transactions in the scope development activities. It helps developers to realize specific tests, and debug EMV Level 2 flows using traces. Using a simple Command Line Interface (CLI), it is possible to trace moka very rapidly using either a PCSC reader (PCSC mode) or virtual cards (VEP-L mode).

Info

Running options are: ``` -h: displays help -c: specifies virtual card -f: specifies config -t: specifies trd -k: specifies cakeys -r: specifies revocations -m: specifies transaction mode (ct or cl) -s: specifies contact kernel ics -v: displays version

```

Info

Type of traces: ``` [DBG]: display miscellaneous traces
[SPC]: displays a reference to EMV Level 2 specification [CERT]: displays information required to valide a certification test [ERR]: displays errors [WRN]: displays warnings

```

Switstack moka Terminal implements a basic EMV Level 3 logic required to certify EMV Level 2 kernels (contact and contactless). This example presents some API calls demonstrating the integration of moka. It is a very simple sequence in regards to acquirer host connection management but it covers key calls to perfrom card processing. Note that there is no specific API for a specific payment brand.

uint16_t
moka_perform_transaction(const char* vcard, const char* trd, const char* issuer)
{
    uint16_t moka_error = MOKA_OK;
    uint8_t buffer[GLASE_MAX_OUTPUT_SIZE_KERNEL_ACTIVATION] = "";
    uint8_t dek[BUFFER_SIZE_512] = "", data[BUFFER_SIZE_512] = ""; // data maybe det or issuer response
    uint16_t buffer_length = 0, dek_length = 0, data_length = 0;
    moka_outcome_parameters_set_t ops;
    moka_bool_t perform_start_d = MOKA_BOOL_TRUE;
    uint32_t transaction_amount = 0;

    /* 1. Pre-processing */
    MOKA_ERROR_FUNC(s_moka_perform_pre_processing(trd, &transaction_amount));

    /* 2. Card selection and presentment */
    MOKA_ERROR_FUNC(moka_present_card(vcard));

    /* 3. Polling ans application selection */
    MOKA_ERROR_FUNC(s_moka_perform_selection(&ops));

    /* 4. Kernel activation */
    while (perform_start_d) {
        emvco_signals_ops_initialize(&ops);
        hal_os_memset(buffer, 0x00, sizeof(buffer));
        buffer_length = sizeof(buffer);
        MOKA_ERROR_FUNC(s_moka_activate_kernel(data, data_length, buffer, &buffer_length));

        /* Search for DEK */
        if (parser_tlv_utils_find_tag_from_tlv(
            MOKA_TAG_STRUCT_DEK, &dek_length, dek, buffer, buffer_length) == MOKA_OK) {
            hal_os_memset(data, 0x00, sizeof(data_length));
            data_length = 0;
            MOKA_ERROR_FUNC(de_ds_perform_operator_logic(
                transaction_amount,
                dek,
                dek_length,
                data,
                &data_length));

            hal_os_memset(dek, 0x00, sizeof(dek_length));
            dek_length = 0;

            // Set entry point with DET: todo -> use start D inbound

            continue;
        };

        MOKA_ERROR_FUNC(s_moka_get_outcome_parameter_set(buffer, buffer_length ,&ops));
        switch (ops.status)
        {
        case OPS_STATUS_APPROVED: 
        case OPS_STATUS_DECLINED:
            perform_start_d = MOKA_BOOL_FALSE;
            break; 
        case OPS_STATUS_ONLINE_REQUEST:
            MOKA_UNUSED(issuer); // For now until scrpts required
            hal_os_memset(data, 0x00, sizeof(data));
            data_length = sizeof(data);
            MOKA_ERROR_FUNC(s_moka_go_online(issuer, data, &data_length));            
            break;
        default:
            break;
        }

        switch (ops.start)
        {
        case START_B:
            MOKA_ERROR_FUNC(s_moka_perform_selection(&ops));
            break; 
        case START_D:
            break;
        default:
            perform_start_d = MOKA_BOOL_FALSE;
            break;
        }
    };

    /* 5. Card removal */
    MOKA_ERROR_FUNC(card.remove());

    return MOKA_OK;
}