From 0e1ab29b8b063b82044156d937c99b589ab27575 Mon Sep 17 00:00:00 2001 From: Leon Lynch Date: Thu, 21 Mar 2024 20:36:15 +0100 Subject: [PATCH] Add emv_tlv_list_find_const() alternative for emv_tlv_list_find() * emv_tlv_list_find_const() is intentionally an inline header function that will not be an external library symbol * Convert as many variables and parameters to be const pointers by using emv_tlv_list_find_const() whenever possible --- src/emv.c | 8 +++---- src/emv_app.c | 24 +++++++++---------- src/emv_dol.c | 8 +++---- src/emv_dol.h | 4 ++-- src/emv_tal.c | 14 +++++------ src/emv_tal.h | 4 ++-- src/emv_tlv.h | 17 +++++++++++++ ...emv_initiate_application_processing_test.c | 16 ++++++------- 8 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/emv.c b/src/emv.c index 26784df..65fad3b 100644 --- a/src/emv.c +++ b/src/emv.c @@ -458,7 +458,7 @@ int emv_initiate_application_processing( // Process PDOL, if available // See EMV 4.4 Book 3, 10.1 - pdol = emv_tlv_list_find(&selected_app->tlv_list, EMV_TAG_9F38_PDOL); + pdol = emv_tlv_list_find_const(&selected_app->tlv_list, EMV_TAG_9F38_PDOL); if (pdol) { int dol_data_len; size_t gpo_data_offset; @@ -494,8 +494,8 @@ int emv_initiate_application_processing( r = emv_dol_build_data( pdol->value, pdol->length, - (struct emv_tlv_list_t*)source1, - (struct emv_tlv_list_t*)source2, + source1, + source2, gpo_data + gpo_data_offset, &gpo_data_len ); @@ -595,7 +595,7 @@ int emv_read_application_data( // Process Application File Locator (AFL) // See EMV 4.4 Book 3, 10.2 - afl = emv_tlv_list_find(icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); + afl = emv_tlv_list_find_const(icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); if (!afl) { // AFL not found; terminate session // See EMV 4.4 Book 3, 6.5.8.4 diff --git a/src/emv_app.c b/src/emv_app.c index 1521421..4a475aa 100644 --- a/src/emv_app.c +++ b/src/emv_app.c @@ -31,7 +31,7 @@ #include // Helper functions -static int emv_app_extract_display_name(struct emv_app_t* app, struct emv_tlv_list_t* pse_tlv_list); +static int emv_app_extract_display_name(struct emv_app_t* app, const struct emv_tlv_list_t* pse_tlv_list); static int emv_app_extract_priority_indicator(struct emv_app_t* app); static inline bool emv_app_list_is_valid(const struct emv_app_list_t* list); @@ -62,7 +62,7 @@ struct emv_app_t* emv_app_create_from_pse( } // Use ADF Name field for AID - app->aid = emv_tlv_list_find(&app->tlv_list, EMV_TAG_4F_APPLICATION_DF_NAME); + app->aid = emv_tlv_list_find_const(&app->tlv_list, EMV_TAG_4F_APPLICATION_DF_NAME); if (!app->aid) { // Invalid FCI goto error; @@ -120,7 +120,7 @@ struct emv_app_t* emv_app_create_from_fci(const void* fci, size_t fci_len) } // Use DF Name field for AID - app->aid = emv_tlv_list_find(&app->tlv_list, EMV_TAG_84_DF_NAME); + app->aid = emv_tlv_list_find_const(&app->tlv_list, EMV_TAG_84_DF_NAME); if (!app->aid) { // Invalid FCI goto error; @@ -143,12 +143,12 @@ struct emv_app_t* emv_app_create_from_fci(const void* fci, size_t fci_len) return NULL; } -static int emv_app_extract_display_name(struct emv_app_t* app, struct emv_tlv_list_t* pse_tlv_list) +static int emv_app_extract_display_name(struct emv_app_t* app, const struct emv_tlv_list_t* pse_tlv_list) { int r; - struct emv_tlv_t* issuer_code_table_index; + const struct emv_tlv_t* issuer_code_table_index; unsigned int issuer_code_table = 0; - struct emv_tlv_t* tlv; + const struct emv_tlv_t* tlv; if (!app) { return -1; @@ -159,9 +159,9 @@ static int emv_app_extract_display_name(struct emv_app_t* app, struct emv_tlv_li * interpret Application Preferred Name */ if (pse_tlv_list) { - issuer_code_table_index = emv_tlv_list_find(pse_tlv_list, EMV_TAG_9F11_ISSUER_CODE_TABLE_INDEX); + issuer_code_table_index = emv_tlv_list_find_const(pse_tlv_list, EMV_TAG_9F11_ISSUER_CODE_TABLE_INDEX); } else { - issuer_code_table_index = emv_tlv_list_find(&app->tlv_list, EMV_TAG_9F11_ISSUER_CODE_TABLE_INDEX); + issuer_code_table_index = emv_tlv_list_find_const(&app->tlv_list, EMV_TAG_9F11_ISSUER_CODE_TABLE_INDEX); } if (issuer_code_table_index && issuer_code_table_index->length == 1) { // Assume Additional Terminal Capabilities (field 9F40) was correctly @@ -173,7 +173,7 @@ static int emv_app_extract_display_name(struct emv_app_t* app, struct emv_tlv_li } if (issuer_code_table) { // Use Application Preferred Name as display name - tlv = emv_tlv_list_find(&app->tlv_list, EMV_TAG_9F12_APPLICATION_PREFERRED_NAME); + tlv = emv_tlv_list_find_const(&app->tlv_list, EMV_TAG_9F12_APPLICATION_PREFERRED_NAME); if (tlv) { // Application Preferred Name is limited to non-control characters // defined in the ISO/IEC 8859 part designated in the Issuer Code @@ -207,7 +207,7 @@ static int emv_app_extract_display_name(struct emv_app_t* app, struct emv_tlv_li } // Otherwise use Application Label as display name - tlv = emv_tlv_list_find(&app->tlv_list, EMV_TAG_50_APPLICATION_LABEL); + tlv = emv_tlv_list_find_const(&app->tlv_list, EMV_TAG_50_APPLICATION_LABEL); if (tlv) { // Application Label is limited to a-z, A-Z, 0-9 and the space // See EMV 4.4 Book 1, 4.3 @@ -242,7 +242,7 @@ static int emv_app_extract_display_name(struct emv_app_t* app, struct emv_tlv_li static int emv_app_extract_priority_indicator(struct emv_app_t* app) { - struct emv_tlv_t* tlv; + const struct emv_tlv_t* tlv; if (!app) { return -1; @@ -251,7 +251,7 @@ static int emv_app_extract_priority_indicator(struct emv_app_t* app) app->priority = 0; app->confirmation_required = false; - tlv = emv_tlv_list_find(&app->tlv_list, EMV_TAG_87_APPLICATION_PRIORITY_INDICATOR); + tlv = emv_tlv_list_find_const(&app->tlv_list, EMV_TAG_87_APPLICATION_PRIORITY_INDICATOR); if (!tlv || tlv->length < 1) { // Application Priority Indicator is not available; ignore return 0; diff --git a/src/emv_dol.c b/src/emv_dol.c index c0603c6..bb02d4f 100644 --- a/src/emv_dol.c +++ b/src/emv_dol.c @@ -127,8 +127,8 @@ int emv_dol_compute_data_length(const void* ptr, size_t len) int emv_dol_build_data( const void* ptr, size_t len, - struct emv_tlv_list_t* source1, - struct emv_tlv_list_t* source2, + const struct emv_tlv_list_t* source1, + const struct emv_tlv_list_t* source2, void* data, size_t* data_len ) @@ -156,9 +156,9 @@ int emv_dol_build_data( } // Find TLV - tlv = emv_tlv_list_find(source1, entry.tag); + tlv = emv_tlv_list_find_const(source1, entry.tag); if (!tlv && source2) { - tlv = emv_tlv_list_find(source2, entry.tag); + tlv = emv_tlv_list_find_const(source2, entry.tag); } if (!tlv) { // If TLV is not found, zero data output diff --git a/src/emv_dol.h b/src/emv_dol.h index 38d2f0a..a52d60c 100644 --- a/src/emv_dol.h +++ b/src/emv_dol.h @@ -93,8 +93,8 @@ int emv_dol_compute_data_length(const void* ptr, size_t len); int emv_dol_build_data( const void* ptr, size_t len, - struct emv_tlv_list_t* source1, - struct emv_tlv_list_t* source2, + const struct emv_tlv_list_t* source1, + const struct emv_tlv_list_t* source2, void* data, size_t* data_len ); diff --git a/src/emv_tal.c b/src/emv_tal.c index cf33d16..f3be937 100644 --- a/src/emv_tal.c +++ b/src/emv_tal.c @@ -127,9 +127,9 @@ int emv_tal_read_pse( // Find Short File Identifier (SFI) for PSE directory Application Elementary File (AEF) // See EMV 4.4 Book 1, 11.3.4, table 8 - pse_sfi = emv_tlv_list_find(&pse_tlv_list, EMV_TAG_88_SFI); + pse_sfi = emv_tlv_list_find_const(&pse_tlv_list, EMV_TAG_88_SFI); if (!pse_sfi) { - emv_debug_trace_msg("emv_tlv_list_find() failed; pse_sfi=%p", pse_sfi); + emv_debug_trace_msg("emv_tlv_list_find_const() failed; pse_sfi=%p", pse_sfi); // Failed to find SFI for PSE records; terminal may continue session // See EMV 4.4 Book 1, 12.3.2, step 1 @@ -544,8 +544,8 @@ int emv_tal_get_processing_options( const void* data, size_t data_len, struct emv_tlv_list_t* list, - struct emv_tlv_t** aip, - struct emv_tlv_t** afl + const struct emv_tlv_t** aip, + const struct emv_tlv_t** afl ) { int r; @@ -554,7 +554,7 @@ int emv_tal_get_processing_options( uint16_t sw1sw2; struct iso8825_tlv_t gpo_tlv; struct emv_tlv_list_t gpo_list = EMV_TLV_LIST_INIT; - struct emv_tlv_t* tlv; + const struct emv_tlv_t* tlv; if (!ttl || !list) { // Invalid parameters; terminate session @@ -696,7 +696,7 @@ int emv_tal_get_processing_options( } // Populate AIP pointer - tlv = emv_tlv_list_find(&gpo_list, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); + tlv = emv_tlv_list_find_const(&gpo_list, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); if (!tlv) { // Mandatory field missing; terminate session // See EMV 4.4 Book 3, 6.5.8.4 @@ -709,7 +709,7 @@ int emv_tal_get_processing_options( } // Populate AFL pointer - tlv = emv_tlv_list_find(&gpo_list, EMV_TAG_94_APPLICATION_FILE_LOCATOR); + tlv = emv_tlv_list_find_const(&gpo_list, EMV_TAG_94_APPLICATION_FILE_LOCATOR); if (!tlv) { // Mandatory field missing; terminate session // See EMV 4.4 Book 3, 6.5.8.4 diff --git a/src/emv_tal.h b/src/emv_tal.h index 0c05538..67eba87 100644 --- a/src/emv_tal.h +++ b/src/emv_tal.h @@ -170,8 +170,8 @@ int emv_tal_get_processing_options( const void* data, size_t data_len, struct emv_tlv_list_t* list, - struct emv_tlv_t** aip, - struct emv_tlv_t** afl + const struct emv_tlv_t** aip, + const struct emv_tlv_t** afl ); /** diff --git a/src/emv_tlv.h b/src/emv_tlv.h index 0c5bedb..91bc1a8 100644 --- a/src/emv_tlv.h +++ b/src/emv_tlv.h @@ -118,6 +118,23 @@ struct emv_tlv_t* emv_tlv_list_pop(struct emv_tlv_list_t* list); */ struct emv_tlv_t* emv_tlv_list_find(struct emv_tlv_list_t* list, unsigned int tag); +/** + * Const alternative for @ref emv_tlv_list_find + * @param list EMV TLV list + * @param tag EMV tag to find + * @return EMV TLV field. Do NOT free. NULL if not found. + */ +#ifdef __GNUC__ +__attribute__((always_inline)) +#endif +inline const struct emv_tlv_t* emv_tlv_list_find_const( + const struct emv_tlv_list_t* list, + unsigned int tag +) +{ + return emv_tlv_list_find((struct emv_tlv_list_t*)list, tag); +} + /** * Determine whether EMV TLV list contains duplicate fields * @param list EMV TLV list diff --git a/tests/emv_initiate_application_processing_test.c b/tests/emv_initiate_application_processing_test.c index 77a6327..158bd5e 100644 --- a/tests/emv_initiate_application_processing_test.c +++ b/tests/emv_initiate_application_processing_test.c @@ -132,8 +132,8 @@ int main(void) struct emv_tlv_list_t source2 = EMV_TLV_LIST_INIT; struct emv_app_t* app = NULL; struct emv_tlv_list_t icc = EMV_TLV_LIST_INIT; - struct emv_tlv_t* aip; - struct emv_tlv_t* afl; + const struct emv_tlv_t* aip; + const struct emv_tlv_t* afl; ttl.cardreader.mode = EMV_CARDREADER_MODE_APDU; ttl.cardreader.ctx = &emul_ctx; @@ -193,7 +193,7 @@ int main(void) r = 1; goto exit; } - aip = emv_tlv_list_find(&icc, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); + aip = emv_tlv_list_find_const(&icc, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); if (!aip) { fprintf(stderr, "Failed to find AIP\n"); r = 1; @@ -208,7 +208,7 @@ int main(void) r = 1; goto exit; } - afl = emv_tlv_list_find(&icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); + afl = emv_tlv_list_find_const(&icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); if (!afl) { fprintf(stderr, "Failed to find AFL\n"); r = 1; @@ -259,7 +259,7 @@ int main(void) r = 1; goto exit; } - aip = emv_tlv_list_find(&icc, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); + aip = emv_tlv_list_find_const(&icc, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); if (!aip) { fprintf(stderr, "Failed to find AIP\n"); r = 1; @@ -274,7 +274,7 @@ int main(void) r = 1; goto exit; } - afl = emv_tlv_list_find(&icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); + afl = emv_tlv_list_find_const(&icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); if (!afl) { fprintf(stderr, "Failed to find AFL\n"); r = 1; @@ -361,7 +361,7 @@ int main(void) r = 1; goto exit; } - aip = emv_tlv_list_find(&icc, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); + aip = emv_tlv_list_find_const(&icc, EMV_TAG_82_APPLICATION_INTERCHANGE_PROFILE); if (!aip) { fprintf(stderr, "Failed to find AIP\n"); r = 1; @@ -376,7 +376,7 @@ int main(void) r = 1; goto exit; } - afl = emv_tlv_list_find(&icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); + afl = emv_tlv_list_find_const(&icc, EMV_TAG_94_APPLICATION_FILE_LOCATOR); if (!afl) { fprintf(stderr, "Failed to find AFL\n"); r = 1;