use apduencode for emv commands

This commit is contained in:
merlokk 2019-07-16 17:04:54 +03:00
commit a30c62137b
3 changed files with 37 additions and 14 deletions

View file

@ -467,6 +467,30 @@ int APDUEncode(APDUStruct *apdu, uint8_t *data, int *len) {
return 0; return 0;
} }
int APDUEncodeS(sAPDU *sapdu, bool extended, uint16_t le, uint8_t *data, int *len) {
if (extended && le > 0x100)
return 10;
APDUStruct apdu;
apdu.cla = sapdu->CLA;
apdu.ins = sapdu->INS;
apdu.p1 = sapdu->P1;
apdu.p2 = sapdu->P2;
apdu.lc = sapdu->Lc;
if (sapdu->Lc)
apdu.data = sapdu->data;
else
apdu.data = NULL;
apdu.le = le;
apdu.extended_apdu = extended;
apdu.case_type = 0x00;
return APDUEncode(&apdu, data, len);
}
void APDUPrint(APDUStruct apdu) { void APDUPrint(APDUStruct apdu) {
APDUPrintEx(apdu, 0); APDUPrintEx(apdu, 0);
} }

View file

@ -65,6 +65,7 @@ typedef struct {
extern int APDUDecode(uint8_t *data, int len, APDUStruct *apdu); extern int APDUDecode(uint8_t *data, int len, APDUStruct *apdu);
extern int APDUEncode(APDUStruct *apdu, uint8_t *data, int *len); extern int APDUEncode(APDUStruct *apdu, uint8_t *data, int *len);
extern int APDUEncodeS(sAPDU *apdu, bool extended, uint16_t le, uint8_t *data, int *len);
extern void APDUPrint(APDUStruct apdu); extern void APDUPrint(APDUStruct apdu);
extern void APDUPrintEx(APDUStruct apdu, size_t maxdatalen); extern void APDUPrintEx(APDUStruct apdu, size_t maxdatalen);

View file

@ -277,24 +277,22 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea
} }
// COMPUTE APDU // COMPUTE APDU
memcpy(data, &apdu, 5); int datalen = 0;
if (apdu.data) APDUEncodeS(&apdu, false, IncludeLe ? 0x100 : 0x00, data, &datalen);
memcpy(&data[5], apdu.data, apdu.Lc);
if (APDULogging) if (APDULogging)
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, (IncludeLe ? 6 : 5) + apdu.Lc)); PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen));
switch (channel) { switch (channel) {
case ECC_CONTACTLESS: case ECC_CONTACTLESS:
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le(?IncludeLe) res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
res = ExchangeAPDU14a(data, (IncludeLe ? 6 : 5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res) { if (res) {
return res; return res;
} }
break; break;
case ECC_CONTACT: case ECC_CONTACT:
if (IfPm3Smartcard()) if (IfPm3Smartcard())
res = ExchangeAPDUSC(data, (IncludeLe ? 6 : 5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); res = ExchangeAPDUSC(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
else else
res = 1; res = 1;
if (res) { if (res) {
@ -336,7 +334,7 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea
} }
int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
return EMVExchangeEx(channel, false, LeaveFieldON, apdu, (channel == ECC_CONTACTLESS), Result, MaxResultLen, ResultLen, sw, tlv); return EMVExchangeEx(channel, false, LeaveFieldON, apdu, false, Result, MaxResultLen, ResultLen, sw, tlv);
} }
int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
@ -609,9 +607,9 @@ int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t P
} }
int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int res = EMVExchange(channel, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700) { if (*sw == 0x6700 || *sw == 0x6f00) {
PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le..."); PrintAndLogEx(INFO, ">>> trying to reissue command without Le...");
res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
} }
return res; return res;
@ -622,9 +620,9 @@ int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint
} }
int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {
int res = EMVExchange(channel, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700) { if (*sw == 0x6700 || *sw == 0x6f00) {
PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le..."); PrintAndLogEx(INFO, ">>> trying to reissue command without Le...");
res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv);
} }
return res; return res;