Merge pull request #253 from merlokk/emv_apdu

Emv apdu
This commit is contained in:
Oleg Moiseenko 2019-07-16 18:08:39 +03:00 committed by GitHub
commit d3b6a8e193
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 23 deletions

View file

@ -467,6 +467,30 @@ int APDUEncode(APDUStruct *apdu, uint8_t *data, int *len) {
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) {
APDUPrintEx(apdu, 0);
}

View file

@ -34,6 +34,15 @@ 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;
uint8_t *data;
} PACKED sAPDU;
typedef struct {
uint8_t cla;
uint8_t ins;
@ -56,6 +65,7 @@ typedef struct {
extern int APDUDecode(uint8_t *data, int len, APDUStruct *apdu);
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 APDUPrintEx(APDUStruct apdu, size_t maxdatalen);

View file

@ -830,6 +830,12 @@ static int CmdEMVExec(const char *Cmd) {
SetAPDULogging(showAPDU);
res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect);
// check PPSE instead of PSE and vice versa
if (res) {
PrintAndLogEx(NORMAL, "Check PPSE instead of PSE and vice versa...");
res = EMVSearchPSE(channel, false, true, psenum == 1 ? 2 : 1, decodeTLV, tlvSelect);
}
// check PPSE and select application id
if (!res) {
TLVPrintAIDlistFromSelectTLV(tlvSelect);

View file

@ -277,24 +277,25 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea
}
// COMPUTE APDU
memcpy(data, &apdu, 5);
if (apdu.data)
memcpy(&data[5], apdu.data, apdu.Lc);
int datalen = 0;
if (APDUEncodeS(&apdu, false, IncludeLe ? 0x100 : 0x00, data, &datalen)) {
PrintAndLogEx(ERR, "APDU encoding error.");
return 201;
}
if (APDULogging)
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, (IncludeLe ? 6 : 5) + apdu.Lc));
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen));
switch (channel) {
case ECC_CONTACTLESS:
// 6 byes + data = INS + CLA + P1 + P2 + Lc + <data = Nc> + Le(?IncludeLe)
res = ExchangeAPDU14a(data, (IncludeLe ? 6 : 5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
if (res) {
return res;
}
break;
case ECC_CONTACT:
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
res = 1;
if (res) {
@ -336,7 +337,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) {
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) {
@ -609,9 +610,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 res = EMVExchange(channel, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700) {
PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le...");
int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700 || *sw == 0x6f00) {
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);
}
return res;
@ -622,9 +623,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 res = EMVExchange(channel, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700) {
PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le...");
int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x00, 0x84, 0x00, 0x00, 0x00, NULL}, true, Result, MaxResultLen, ResultLen, sw, tlv);
if (*sw == 0x6700 || *sw == 0x6f00) {
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);
}
return res;

View file

@ -45,15 +45,6 @@ enum TransactionType {
};
extern const char *TransactionTypeStr[];
typedef struct {
uint8_t CLA;
uint8_t INS;
uint8_t P1;
uint8_t P2;
uint8_t Lc;
uint8_t *data;
} sAPDU;
enum CardPSVendor {
CV_NA,
CV_VISA,