Skip to content

Commit

Permalink
Refactor discovery of supported apps
Browse files Browse the repository at this point in the history
* Update comments to EMV 4.4
* Use TAL result enums
* Add logging for all code paths
* Identify R-APDU status 6A82 (Application not found) for logging
* Let supported_aids parameter be const
  • Loading branch information
leonlynch committed Jan 17, 2024
1 parent cad512d commit 72a6a2a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
66 changes: 43 additions & 23 deletions src/emv_tal.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ static int emv_tal_parse_aef_record(

int emv_tal_find_supported_apps(
struct emv_ttl_t* ttl,
struct emv_tlv_list_t* supported_aids,
const struct emv_tlv_list_t* supported_aids,
struct emv_app_list_t* app_list
)
{
Expand All @@ -293,7 +293,7 @@ int emv_tal_find_supported_apps(

if (!ttl || !supported_aids || !app_list) {
// Invalid parameters; terminate session
return -1;
return EMV_TAL_ERROR_INVALID_PARAMETER;
}

aid = supported_aids->front;
Expand All @@ -307,35 +307,48 @@ int emv_tal_find_supported_apps(

if (exact_match) {
// SELECT application
// See EMV 4.3 Book 1, 12.3.3, step 1
// See EMV 4.4 Book 1, 12.3.3, step 1
emv_debug_info_data("SELECT application", aid->value, aid->length);
r = emv_ttl_select_by_df_name(ttl, aid->value, aid->length, fci, &fci_len, &sw1sw2);
if (r) {
emv_debug_trace_msg("emv_ttl_select_by_df_name() failed; r=%d", r);

// TTL failure; terminate session
// (bad card or reader)
return -2;
emv_debug_error("TTL failure");
return EMV_TAL_ERROR_TTL_FAILURE;
}

if (sw1sw2 == 0x6A81) {
// Card blocked or SELECT not supported; terminate session
// See EMV 4.3 Book 1, 12.3.3, step 2
return -3;
// See EMV 4.4 Book 1, 12.3.3, step 2
emv_debug_error("Card blocked or SELECT not supported");
return EMV_TAL_ERROR_CARD_BLOCKED;
}

} else {
// SELECT next application for partial AID match
// See EMV 4.3 Book 1, 12.3.3, step 7
// See EMV 4.4 Book 1, 12.3.3, step 7
emv_debug_info_data("SELECT next application", aid->value, aid->length);
r = emv_ttl_select_by_df_name_next(ttl, aid->value, aid->length, fci, &fci_len, &sw1sw2);
if (r) {
emv_debug_trace_msg("emv_ttl_select_by_df_name_next() failed; r=%d", r);

// TTL failure; terminate session
// (bad card or reader)
return -2;
emv_debug_error("TTL failure");
return EMV_TAL_ERROR_TTL_FAILURE;
}

}

if (sw1sw2 != 0x9000 && sw1sw2 != 0x6283) {
// Unexpected error; ignore app and continue to next supported AID
// See EMV 4.3 Book 1, 12.3.3, step 3
// Unexpected SELECT status; ignore app and continue to next supported AID
// See EMV 4.4 Book 1, 12.3.3, step 3
if (sw1sw2 == 0x6A82) {
emv_debug_info("Application not found");
} else {
emv_debug_error("Unexpected SELECT status 0x%04X", sw1sw2);
}
aid = aid->next;
exact_match = true;
continue;
Expand All @@ -344,11 +357,13 @@ int emv_tal_find_supported_apps(
emv_debug_info_tlv("FCI", fci, fci_len);

// Extract FCI data
// See EMV 4.3 Book 1, 12.3.3, step 3
// See EMV 4.4 Book 1, 12.3.3, step 3
app = emv_app_create_from_fci(fci, fci_len);
if (!app) {
emv_debug_trace_msg("emv_app_create_from_fci() failed; app=%p", app);

// Unexpected error; ignore app and continue to next supported AID
// See EMV 4.3 Book 1, 12.3.3, step 3
// See EMV 4.4 Book 1, 12.3.3, step 3
aid = aid->next;
exact_match = true;
continue;
Expand All @@ -361,53 +376,58 @@ int emv_tal_find_supported_apps(

if (aid->length == app->aid->length) {
// Exact match; check whether valid or blocked
// See EMV 4.3 Book 1, 12.3.3, step 4
// See EMV 4.4 Book 1, 12.3.3, step 4

if (sw1sw2 == 0x9000) {
// Valid app; add app and continue to next supported AID
// See EMV 4.3 Book 1, 12.3.3, step 4
// See EMV 4.4 Book 1, 12.3.3, step 4
emv_debug_info("Application is supported: exact match");
emv_app_list_push(app_list, app);
} else {
// Blocked app; ignore app and continue to next supported AID
// See EMV 4.3 Book 1, 12.3.3, step 4
// See EMV 4.4 Book 1, 12.3.3, step 4
emv_debug_info("Application is blocked");
emv_app_free(app);
app = NULL;
}

// See EMV 4.3 Book 1, 12.3.3, step 5
// See EMV 4.4 Book 1, 12.3.3, step 5
aid = aid->next;
exact_match = true;
continue;

} else {
// Partial match; check Application Selection Indicator (ASI)
// See EMV 4.3 Book 1, 12.3.3, step 6
// See EMV 4.4 Book 1, 12.3.3, step 6

if (aid->flags == EMV_ASI_PARTIAL_MATCH) {
// Partial match allowed; check whether valid or blocked

if (sw1sw2 == 0x9000) {
// Valid app; add app and continue to next partial AID
// See EMV 4.3 Book 1, 12.3.3, step 6
// See EMV 4.4 Book 1, 12.3.3, step 6
emv_debug_info("Application is supported: partial match");
emv_app_list_push(app_list, app);
} else {
// Blocked app; ignore app and continue to next partial AID
// See EMV 4.3 Book 1, 12.3.3, step 6
// See EMV 4.4 Book 1, 12.3.3, step 6
emv_debug_info("Application is blocked");
emv_app_free(app);
app = NULL;
}

// See EMV 4.3 Book 1, 12.3.3, step 7
// See EMV 4.4 Book 1, 12.3.3, step 7
exact_match = false;
continue;

} else {
// Partial match not allowed; ignore app and continue to next supported AID
// See EMV 4.3 Book 1, 12.3.3, step 6
// See EMV 4.4 Book 1, 12.3.3, step 6
emv_debug_info("Application is not supported: partial match not allowed");
emv_app_free(app);
app = NULL;

// See EMV 4.3 Book 1, 12.3.3, step 5
// See EMV 4.4 Book 1, 12.3.3, step 5
aid = aid->next;
exact_match = true;
continue;
Expand Down
8 changes: 4 additions & 4 deletions src/emv_tal.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,20 @@ int emv_tal_read_pse(
);

/**
* Find supported applications and build application list
* @remark See EMV 4.3 Book 1, 12.3.3
* Find supported applications and build candidate application list
* @remark See EMV 4.4 Book 1, 12.3.3
*
* @param ttl EMV Terminal Transport Layer context
* @param supported_aids Supported AID (field 9F06) list including ASI flags
* @param app_list Candidate application list output
*
* @return Zero for success
* @return Less than zero indicates that the terminal should terminate the
* card session.
* card session. See @ref emv_tal_error_t
*/
int emv_tal_find_supported_apps(
struct emv_ttl_t* ttl,
struct emv_tlv_list_t* supported_aids,
const struct emv_tlv_list_t* supported_aids,
struct emv_app_list_t* app_list
);

Expand Down

0 comments on commit 72a6a2a

Please sign in to comment.