mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-19 19:38:52 +08:00
commit
d3b6a8e193
5 changed files with 55 additions and 23 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue