diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c index df44ef961..6deeb618b 100644 --- a/client/emv/apduinfo.c +++ b/client/emv/apduinfo.c @@ -314,3 +314,115 @@ const char *GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2) { else return APDUCodeTable[0].Description; //empty string } + +int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu) +{ + EXT_APDU_HEADER *hapdu = (EXT_APDU_HEADER *)data; + + apdu->cla = hapdu->cla; + apdu->ins = hapdu->ins; + apdu->p1 = hapdu->p1; + apdu->p2 = hapdu->p2; + + apdu->lc = 0; + apdu->data = NULL; + apdu->le = 0; + apdu->extended_apdu = false; + apdu->case_type = 0x00; + + uint8_t b0 = hapdu->lc[0]; + + // case 1 + if (len == 4) + { + apdu->case_type = 0x01; + } + + // case 2S (Le) + if (len == 5) + { + apdu->case_type = 0x02; + apdu->le = b0; + if (!apdu->le) + apdu->le = 0x100; + } + + // case 3S (Lc + data) + if (len == 5U + b0 && b0 != 0) + { + apdu->case_type = 0x03; + apdu->lc = b0; + } + + // case 4S (Lc + data + Le) + if (len == 5U + b0 + 1U && b0 != 0) + { + apdu->case_type = 0x04; + apdu->lc = b0; + apdu->le = data[len - 1]; + if (!apdu->le) + apdu->le = 0x100; + } + + // extended length apdu + if (len >= 7 && b0 == 0) + { + uint16_t extlen = (hapdu->lc[1] << 8) + hapdu->lc[2]; + + // case 2E (Le) - extended + if (len == 7) + { + apdu->case_type = 0x12; + apdu->extended_apdu = true; + apdu->le = extlen; + if (!apdu->le) + apdu->le = 0x10000; + } + + // case 3E (Lc + data) - extended + if (len == 7U + extlen) + { + apdu->case_type = 0x13; + apdu->extended_apdu = true; + apdu->lc = extlen; + } + + // case 4E (Lc + data + Le) - extended 2-byte Le + if (len == 7U + extlen + 2U) + { + apdu->case_type = 0x14; + apdu->extended_apdu = true; + apdu->lc = extlen; + apdu->le = (data[len - 2] << 8) + data[len - 1]; + if (!apdu->le) + apdu->le = 0x10000; + } + + // case 4E (Lc + data + Le) - extended 3-byte Le + if (len == 7U + extlen + 3U && data[len - 3] == 0) + { + apdu->case_type = 0x24; + apdu->extended_apdu = true; + apdu->lc = extlen; + apdu->le = (data[len - 2] << 8) + data[len - 1]; + if (!apdu->le) + apdu->le = 0x10000; + } + } + + if (!apdu->case_type) + return 1; + + if (apdu->lc) + { + if (apdu->extended_apdu) + { + apdu->data = data + 7; + } else { + apdu->data = data + 5; + } + + } + + return 0; +} diff --git a/client/emv/apduinfo.h b/client/emv/apduinfo.h index 317d661ff..399fd44a1 100644 --- a/client/emv/apduinfo.h +++ b/client/emv/apduinfo.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #define APDUCODE_TYPE_NONE 0 @@ -31,4 +32,28 @@ typedef struct { const APDUCode *GetAPDUCode(uint8_t sw1, uint8_t sw2); const char *GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2); +typedef struct +{ + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t lc[3]; +} __attribute__((packed)) EXT_APDU_HEADER; + +typedef struct +{ + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint16_t lc; + uint8_t *data; + uint32_t le; + bool extended_apdu; + uint8_t case_type; +} __attribute__((packed)) APDU_STRUCT; +extern int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu); + + #endif