From 9ceae3a3b28c7a25002434aca12e7f70e9fd5fe7 Mon Sep 17 00:00:00 2001 From: Nikita Vostokov <1042932+wosk@users.noreply.github.com> Date: Fri, 2 Feb 2024 00:20:31 +0000 Subject: [PATCH] [EMV] Fix crash while PDOL parsing --- lib/nfc/protocols/emv/emv_poller_i.c | 56 ++++++++++++---------------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/lib/nfc/protocols/emv/emv_poller_i.c b/lib/nfc/protocols/emv/emv_poller_i.c index c237125b2..bdf1ecce4 100644 --- a/lib/nfc/protocols/emv/emv_poller_i.c +++ b/lib/nfc/protocols/emv/emv_poller_i.c @@ -76,39 +76,6 @@ static void emv_trace(EmvPoller* instance, const char* message) { } } -static uint16_t emv_prepare_pdol(APDU* dest, APDU* src) { - bool tag_found; - for(uint16_t i = 0; i < src->size; i++) { - tag_found = false; - for(uint8_t j = 0; j < sizeof(pdol_values) / sizeof(PDOLValue*); j++) { - if(src->data[i] == pdol_values[j]->tag) { - // Found tag with 1 byte length - uint8_t len = src->data[++i]; - memcpy(dest->data + dest->size, pdol_values[j]->data, len); - dest->size += len; - tag_found = true; - break; - } else if(((src->data[i] << 8) | src->data[i + 1]) == pdol_values[j]->tag) { - // Found tag with 2 byte length - i += 2; - uint8_t len = src->data[i]; - memcpy(dest->data + dest->size, pdol_values[j]->data, len); - dest->size += len; - tag_found = true; - break; - } - } - if(!tag_found) { - // Unknown tag, fill zeros - i += 2; - uint8_t len = src->data[i]; - memset(dest->data + dest->size, 0, len); - dest->size += len; - } - } - return dest->size; -} - static bool emv_decode_tlv_tag(const uint8_t* buff, uint16_t tag, uint8_t tlen, EmvApplication* app) { uint8_t i = 0; @@ -406,6 +373,29 @@ static bool emv_decode_response_tlv(const uint8_t* buff, uint8_t len, EmvApplica return success; } +static void emv_prepare_pdol(APDU* dest, APDU* src) { + uint16_t tag = 0; + uint8_t tlen = 0; + uint8_t i = 0; + while(i < src->size) { + bool tag_found = emv_parse_tag(src->data, src->size, &tag, &tlen, &i); + if(tag_found) { + for(uint8_t j = 0; j < COUNT_OF(pdol_values); j++) { + if(tag == pdol_values[j]->tag) { + memcpy(dest->data + dest->size, pdol_values[j]->data, tlen); + dest->size += tlen; + break; + } + } + } else { + // Unknown tag, fill zeros + furi_check(dest->size + tlen < sizeof(dest->data)); + memset(dest->data + dest->size, 0, tlen); + dest->size += tlen; + } + } +} + EmvError emv_poller_select_ppse(EmvPoller* instance) { EmvError error = EmvErrorNone;