From 628eceb5ed7b56a32cffba38e6c4095a45acba32 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:44:51 +0200 Subject: [PATCH 1/8] print fix --- client/emv/emvcore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 5ea9026c2..023035a7d 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -795,7 +795,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { return 4; } - PrintAndLogEx(NORMAL, "\n* Calc DDOL"); + PrintAndLogEx(NORMAL, "\n* * Calc DDOL"); const struct tlv *ddol_tlv = tlvdb_get(tlv, 0x9f49, NULL); if (!ddol_tlv) { ddol_tlv = &default_ddol_tlv; @@ -813,7 +813,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { PrintAndLogEx(NORMAL, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); - PrintAndLogEx(NORMAL, "\n* Internal Authenticate"); + PrintAndLogEx(NORMAL, "\n* * Internal Authenticate"); int res = EMVInternalAuthenticate(channel, true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL); if (res) { PrintAndLogEx(WARNING, "Internal Authenticate error(%d): %4x. Exit...", res, sw); @@ -840,7 +840,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { tlvdb_free(t80); if (decodeTLV){ - PrintAndLogEx(NORMAL, "* * Decode response format 1:"); + PrintAndLogEx(NORMAL, "* * * Decode response format 1:"); TLVPrintFromTLV(dda_db); } } @@ -875,12 +875,12 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { // 9f4c ICC Dynamic Number const struct tlv *idn_tlv = tlvdb_get(idn_db, 0x9f4c, NULL); if(idn_tlv) { - PrintAndLogEx(NORMAL, "\nIDN (ICC Dynamic Number) [%zu] %s", idn_tlv->len, sprint_hex_inrow(idn_tlv->value, idn_tlv->len)); - PrintAndLogEx(NORMAL, "DDA verified OK."); + PrintAndLogEx(INFO, "\nIDN (ICC Dynamic Number) [%zu] %s", idn_tlv->len, sprint_hex_inrow(idn_tlv->value, idn_tlv->len)); + PrintAndLogEx(INFO, "DDA verified OK."); tlvdb_add(tlv, idn_db); tlvdb_free(idn_db); } else { - PrintAndLogEx(NORMAL, "\nERROR: DDA verify error"); + PrintAndLogEx(ERR, "\nDDA verify error"); tlvdb_free(idn_db); emv_pk_free(pk); From eaedf7f81101e972887ad749cdb99ef29c3188a2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 18:33:21 +0200 Subject: [PATCH 2/8] VSDC up to CDOL2 calc --- client/emv/cmdemv.c | 17 +++++++++++++++++ client/emv/tlv.c | 12 +++++++++++- client/emv/tlv.h | 2 ++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a30c22aec..114aca322 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1209,6 +1209,23 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); + // needs to send AC2 command (res == ARQC) + uint8_t CID = 0; + tlvdb_get_uint8(tlvRoot, 0x9f27, &CID); + if ((CID & 0xc0) == 0x80) { + PrintAndLogEx(NORMAL, "* * Calc CDOL2"); + struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol_data_tlv) { + PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); + dreturn(6); + } + + PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + + PrintAndLogEx(NORMAL, "* * AC2"); + + + } } diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 9722c9311..8d1429640 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -469,7 +469,10 @@ const struct tlv *tlvdb_get_inchild(const struct tlvdb *tlvdb, tlv_tag_t tag, co } const struct tlv *tlvdb_get_tlv(const struct tlvdb *tlvdb) { - return &tlvdb->tag; + if (tlvdb) + return &tlvdb->tag; + else + return NULL; } unsigned char *tlv_encode(const struct tlv *tlv, size_t *len) @@ -546,6 +549,13 @@ struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) return tlvdb->parent; } +bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value) +{ + const struct tlvdb *tlvdb = tlvdb_get(tlvRoot, tag, NULL); + const struct tlv *tlvelm = tlvdb_get_tlv(tlvdb); + return tlv_get_uint8(tlvelm, value); +} + bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) { *value = 0; diff --git a/client/emv/tlv.h b/client/emv/tlv.h index 1f52e440b..e75bbf986 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -65,4 +65,6 @@ bool tlv_equal(const struct tlv *a, const struct tlv *b); bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value); bool tlv_get_int(const struct tlv *etlv, int *value); +bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value); + #endif From e058d87dc11ec2c3117d8848ea68b54a9c779e65 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 19:28:43 +0200 Subject: [PATCH 3/8] fix CDOL generation and add AC1 print result --- client/emv/cmdemv.c | 35 +++++++++++++++++++++++++---------- client/emv/emv_tags.h | 4 ++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 114aca322..07543241c 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1182,17 +1182,17 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n--> VSDC transaction."); PrintAndLogEx(NORMAL, "* * Calc CDOL1"); - struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag - if (!cdol_data_tlv) { + struct tlv *cdol1_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol1_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV."); dreturn(6); } - PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol1_data_tlv->len, sprint_hex(cdol1_data_tlv->value, cdol1_data_tlv->len)); PrintAndLogEx(NORMAL, "* * AC1"); // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD - res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol1_data_tlv->value, cdol1_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); @@ -1201,7 +1201,17 @@ int CmdEMVExec(const char *cmd) { // process Format1 (0x80) anf print Format2 (0x77) ProcessACResponseFormat1(tlvRoot, buf, len, decodeTLV); - + + uint8_t CID = 0; + tlvdb_get_uint8(tlvRoot, 0x9f27, &CID); + + // AC1 print result + PrintAndLog(""); + if ((CID & EMVAC_AC_MASK) == EMVAC_AAC) PrintAndLogEx(INFO, "AC1 result: AAC (Transaction declined)"); + if ((CID & EMVAC_AC_MASK) == EMVAC_TC) PrintAndLogEx(INFO, "AC1 result: TC (Transaction approved)"); + if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)"); + if ((CID & EMVAC_AC_MASK) == EMVAC_AC_MASK) PrintAndLogEx(INFO, "AC1 result: RFU"); + PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); // authorization response code from acquirer @@ -1210,21 +1220,26 @@ int CmdEMVExec(const char *cmd) { tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); // needs to send AC2 command (res == ARQC) - uint8_t CID = 0; - tlvdb_get_uint8(tlvRoot, 0x9f27, &CID); if ((CID & 0xc0) == 0x80) { PrintAndLogEx(NORMAL, "* * Calc CDOL2"); - struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag - if (!cdol_data_tlv) { + struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol2_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); dreturn(6); } - PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len)); PrintAndLogEx(NORMAL, "* * AC2"); +/* // AC2 + PRINT_INDENT(level); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); +*/ } } diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index 246fc72d7..f7d9a8476 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -25,6 +25,10 @@ # define EMVAC_TC 0x40 # define EMVAC_ARQC 0x80 # define EMVAC_CDAREQ 0x10 +# define EMVAC_AC2_MASK 0x30 +# define EMVAC_AAC2 0x00 +# define EMVAC_TC2 0x10 +# define EMVAC_ARQC2 0x20 // CID # define EMVCID_ADVICE 0x08 From 6f0cc5fa7a8a752b8b93a0ae89ae6379a294f60b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 14 Jan 2019 18:14:15 +0200 Subject: [PATCH 4/8] small fix --- client/emv/cmdemv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 07543241c..71cf542db 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -715,7 +715,7 @@ void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, b TLVPrintFromTLV(tlvElm); // AC (Application Cryptogram) - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, min(8, elmlen - 3), &buf[5], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); @@ -1233,12 +1233,12 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "* * AC2"); -/* // AC2 - PRINT_INDENT(level); - if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); +/* // AC2 + PRINT_INDENT(level); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); */ } From 26bca369292dc7cb6ae39762555c4bbf6e250ff1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 18:39:05 +0200 Subject: [PATCH 5/8] delete comment --- client/emv/emvcore.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 6ccee471c..7af08690c 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -263,7 +263,6 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField break; case ECC_CONTACT: #ifdef WITH_SMARTCARD - //int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); #else res = 1; From 56c9bcc03a6d4c42e3aea902eb5d7d3c7bfb8651 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 21:15:54 +0200 Subject: [PATCH 6/8] added IAD decoding and some improvements --- client/emv/cmdemv.c | 75 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index d0015ac38..477062d38 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1212,16 +1212,79 @@ int CmdEMVExec(const char *cmd) { if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)"); if ((CID & EMVAC_AC_MASK) == EMVAC_AC_MASK) PrintAndLogEx(INFO, "AC1 result: RFU"); - PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); + // decode Issuer Application Data (IAD) + uint8_t CryptoVersion = 0; + const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9f10, NULL); + if (IAD && (IAD->len > 1)) { + PrintAndLogEx(NORMAL, "\n* * Issuer Application Data (IAD):"); + uint8_t VDDlen = IAD->value[0]; // Visa discretionary data length + uint8_t IDDlen = 0; // Issuer discretionary data length + PrintAndLogEx(NORMAL, "IAD length: %d", IAD->len); + PrintAndLogEx(NORMAL, "VDDlen: %d", VDDlen); + if (VDDlen < IAD->len - 1) + IDDlen = IAD->value[VDDlen + 1]; + PrintAndLogEx(NORMAL, "IDDlen: %d", IDDlen); + + uint8_t DerivKeyIndex = IAD->value[1]; + CryptoVersion = IAD->value[2]; + + PrintAndLogEx(NORMAL, "CryptoVersion: %d", CryptoVersion); + PrintAndLogEx(NORMAL, "DerivKeyIndex: %d", DerivKeyIndex); + + // Card Verification Results (CVR) decode + if ((VDDlen - 2) > 0) { + uint8_t CVRlen = IAD->value[3]; + if (CVRlen == (VDDlen - 2 - 1)) { + PrintAndLogEx(NORMAL, "CVR length: %d", CVRlen); + PrintAndLogEx(NORMAL, "CVR: %s", sprint_hex(&IAD->value[4], CVRlen)); + } else { + PrintAndLogEx(NORMAL, "Wrong CVR length! CVR: %s", sprint_hex(&IAD->value[3], VDDlen - 2)); + } + } + if (IDDlen) + PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen)); + } else { + PrintAndLogEx(NORMAL, "Issuer Application Data (IAD) not found."); + } + + PrintAndLogEx(NORMAL, "\n* * Processing online request"); // authorization response code from acquirer const char HostResponse[] = "00"; // 0x3030 - PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); - tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); + size_t HostResponseLen = sizeof(HostResponse) - 1; + PrintAndLogEx(NORMAL, "Host Response: `%s`", HostResponse); + tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse); + if (CryptoVersion == 10) { + PrintAndLogEx(NORMAL, "\n* * Generate ARPC"); + + // Application Cryptogram (AC) + const struct tlv *AC = tlvdb_get(tlvRoot, 0x9f26, NULL); + if (AC && (AC->len > 0)) { + PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len)); + + size_t rawARPClen = AC->len; + uint8_t rawARPC[rawARPClen]; + memcpy(rawARPC, AC->value, AC->len); + for (int i = 0; (i < HostResponseLen) && (i < rawARPClen); i++) + rawARPC[i] ^= HostResponse[i]; + PrintAndLogEx(NORMAL, "raw ARPC: %s", sprint_hex(rawARPC, rawARPClen)); + + // here must be calculation of ARPC, but we dont know a bank keys. + PrintAndLogEx(NORMAL, "ARPC: n/a"); + + } else { + PrintAndLogEx(NORMAL, "Application Cryptogram (AC) not found."); + } + + // here must be external authenticate, but we dont know ARPC + + } + + // needs to send AC2 command (res == ARQC) if ((CID & 0xc0) == 0x80) { - PrintAndLogEx(NORMAL, "* * Calc CDOL2"); + PrintAndLogEx(NORMAL, "\n* * Calc CDOL2"); struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol2_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); @@ -1230,9 +1293,11 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len)); - PrintAndLogEx(NORMAL, "* * AC2"); + //PrintAndLogEx(NORMAL, "* * AC2"); + // here must be AC2, but we dont make external authenticate ( + /* // AC2 PRINT_INDENT(level); if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); From 25d6a1274f33d8cb9a34586ebecc8af29af0236c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 21:19:45 +0200 Subject: [PATCH 7/8] small improvement --- client/emv/cmdemv.c | 2 +- client/emv/emvcore.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 477062d38..e2988e1e7 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1283,7 +1283,7 @@ int CmdEMVExec(const char *cmd) { // needs to send AC2 command (res == ARQC) - if ((CID & 0xc0) == 0x80) { + if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) { PrintAndLogEx(NORMAL, "\n* * Calc CDOL2"); struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol2_data_tlv) { diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 7d53e83bb..9aaaf2e6f 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -39,7 +39,7 @@ typedef enum { enum TransactionType { TT_MSD, - TT_VSDC, // not standart for contactless!!!! + TT_VSDC, // contact only. not standart for contactless TT_QVSDCMCHIP, TT_CDA, }; From e793fa8d73d4cf4e9fe6c16e4447beb4c6e9df74 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 21:28:19 +0200 Subject: [PATCH 8/8] fix tlvdb_get_uint8 --- client/emv/tlv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 8d1429640..0daedaf47 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -551,8 +551,7 @@ struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value) { - const struct tlvdb *tlvdb = tlvdb_get(tlvRoot, tag, NULL); - const struct tlv *tlvelm = tlvdb_get_tlv(tlvdb); + const struct tlv *tlvelm = tlvdb_get(tlvRoot, tag, NULL); return tlv_get_uint8(tlvelm, value); }