mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 14:13:42 -07:00
SDA works
This commit is contained in:
parent
8d9526f375
commit
667a1beafb
3 changed files with 48 additions and 22 deletions
|
@ -308,6 +308,8 @@ int CmdHFEMVExec(const char *cmd) {
|
||||||
uint16_t sw = 0;
|
uint16_t sw = 0;
|
||||||
uint8_t AID[APDU_AID_LEN] = {0};
|
uint8_t AID[APDU_AID_LEN] = {0};
|
||||||
size_t AIDlen = 0;
|
size_t AIDlen = 0;
|
||||||
|
uint8_t ODAiList[4096];
|
||||||
|
size_t ODAiListLen = 0;
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
@ -568,9 +570,23 @@ int CmdHFEMVExec(const char *cmd) {
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build Input list for Offline Data Authentication
|
||||||
|
// EMV 4.3 book3 10.3, page 96
|
||||||
if (SFIoffline) {
|
if (SFIoffline) {
|
||||||
// here will be offline records storing...
|
if (SFI < 11) {
|
||||||
// dont foget: if (sfi < 11)
|
const unsigned char *abuf = buf;
|
||||||
|
size_t elmlen = len;
|
||||||
|
struct tlv e;
|
||||||
|
if (tlv_parse_tl(&abuf, &elmlen, &e)) {
|
||||||
|
memcpy(&ODAiList[ODAiListLen], &buf[len - elmlen], elmlen);
|
||||||
|
ODAiListLen += elmlen;
|
||||||
|
} else {
|
||||||
|
PrintAndLog("ERROR SFI[%02x]. Creating input list for Offline Data Authentication error.", SFI);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(&ODAiList[ODAiListLen], buf, len);
|
||||||
|
ODAiListLen += len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -578,6 +594,13 @@ int CmdHFEMVExec(const char *cmd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy Input list for Offline Data Authentication
|
||||||
|
if (ODAiListLen) {
|
||||||
|
struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag
|
||||||
|
tlvdb_add(tlvRoot, oda);
|
||||||
|
PrintAndLog("* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen);
|
||||||
|
}
|
||||||
|
|
||||||
// get AIP
|
// get AIP
|
||||||
const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
|
const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
|
||||||
uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
|
uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;
|
||||||
|
|
|
@ -177,7 +177,7 @@ static const struct emv_tag emv_tags[] = {
|
||||||
{ 0x01 , "", EMV_TAG_STRING }, // string for headers
|
{ 0x01 , "", EMV_TAG_STRING }, // string for headers
|
||||||
{ 0x02 , "Raw data", }, // data
|
{ 0x02 , "Raw data", }, // data
|
||||||
{ 0x20 , "Cardholder Verification Results (CVR)", EMV_TAG_CVR }, // not standard!
|
{ 0x20 , "Cardholder Verification Results (CVR)", EMV_TAG_CVR }, // not standard!
|
||||||
{ 0x21 , "SDA data" }, // not standard! data for offline authentication from read records command
|
{ 0x21 , "Input list for Offline Data Authentication" }, // not standard! data for "Offline Data Authentication" come from "read records" command. (EMV book3 10.3)
|
||||||
|
|
||||||
// EMV
|
// EMV
|
||||||
{ 0x41 , "Country code and national data" },
|
{ 0x41 , "Country code and national data" },
|
||||||
|
|
|
@ -492,7 +492,7 @@ int trSDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
|
||||||
|
|
||||||
struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv);
|
struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv);
|
||||||
if (!issuer_pk) {
|
if (!issuer_pk) {
|
||||||
PrintAndLog("ERROR: Issuer certificate found. Exit.");
|
PrintAndLog("ERROR: Issuer certificate not found. Exit.");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,14 +510,14 @@ int trSDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
|
||||||
|
|
||||||
const struct tlv *sda_tlv = tlvdb_get(tlv, 0x21, NULL);
|
const struct tlv *sda_tlv = tlvdb_get(tlv, 0x21, NULL);
|
||||||
if (!sda_tlv || sda_tlv->len < 1) {
|
if (!sda_tlv || sda_tlv->len < 1) {
|
||||||
PrintAndLog("ERROR: Can't find dynamic authentication data. Exit.");
|
PrintAndLog("ERROR: Can't find input list for Offline Data Authentication. Exit.");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
|
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
|
||||||
if (dac_db) {
|
if (dac_db) {
|
||||||
const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL);
|
const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL);
|
||||||
PrintAndLog("SDA verified OK (%02hhx:%02hhx)!\n", dac_tlv->value[0], dac_tlv->value[1]);
|
PrintAndLog("SDA verified OK. (%02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]);
|
||||||
tlvdb_add(tlv, dac_db);
|
tlvdb_add(tlv, dac_db);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLog("ERROR: SSAD verify error");
|
PrintAndLog("ERROR: SSAD verify error");
|
||||||
|
@ -538,27 +538,30 @@ int trDDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
|
||||||
|
|
||||||
const struct tlv *sda_tlv = tlvdb_get(tlv, 0x21, NULL);
|
const struct tlv *sda_tlv = tlvdb_get(tlv, 0x21, NULL);
|
||||||
if (!sda_tlv || sda_tlv->len < 1) {
|
if (!sda_tlv || sda_tlv->len < 1) {
|
||||||
PrintAndLog("ERROR: Can't find dynamic authentication data. Exit.");
|
PrintAndLog("ERROR: Can't find input list for Offline Data Authentication. Exit.");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv);
|
struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv);
|
||||||
if (issuer_pk)
|
if (!issuer_pk) {
|
||||||
printf("Issuer PK recovered! RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
PrintAndLog("ERROR: Issuer certificate not found. Exit.");
|
||||||
issuer_pk->rid[0],
|
return 2;
|
||||||
issuer_pk->rid[1],
|
}
|
||||||
issuer_pk->rid[2],
|
printf("Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
||||||
issuer_pk->rid[3],
|
issuer_pk->rid[0],
|
||||||
issuer_pk->rid[4],
|
issuer_pk->rid[1],
|
||||||
issuer_pk->index,
|
issuer_pk->rid[2],
|
||||||
issuer_pk->serial[0],
|
issuer_pk->rid[3],
|
||||||
issuer_pk->serial[1],
|
issuer_pk->rid[4],
|
||||||
issuer_pk->serial[2]
|
issuer_pk->index,
|
||||||
);
|
issuer_pk->serial[0],
|
||||||
|
issuer_pk->serial[1],
|
||||||
|
issuer_pk->serial[2]
|
||||||
|
);
|
||||||
|
|
||||||
struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv);
|
struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv);
|
||||||
if (icc_pk)
|
if (icc_pk)
|
||||||
printf("ICC PK recovered! RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
printf("ICC PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
||||||
icc_pk->rid[0],
|
icc_pk->rid[0],
|
||||||
icc_pk->rid[1],
|
icc_pk->rid[1],
|
||||||
icc_pk->rid[2],
|
icc_pk->rid[2],
|
||||||
|
@ -571,7 +574,7 @@ int trDDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
|
||||||
);
|
);
|
||||||
struct emv_pk *icc_pe_pk = emv_pki_recover_icc_pe_cert(issuer_pk, tlv);
|
struct emv_pk *icc_pe_pk = emv_pki_recover_icc_pe_cert(issuer_pk, tlv);
|
||||||
if (icc_pe_pk)
|
if (icc_pe_pk)
|
||||||
printf("ICC PE PK recovered! RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
printf("ICC PE PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
||||||
icc_pe_pk->rid[0],
|
icc_pe_pk->rid[0],
|
||||||
icc_pe_pk->rid[1],
|
icc_pe_pk->rid[1],
|
||||||
icc_pe_pk->rid[2],
|
icc_pe_pk->rid[2],
|
||||||
|
@ -585,7 +588,7 @@ int trDDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
|
||||||
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
|
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
|
||||||
if (dac_db) {
|
if (dac_db) {
|
||||||
const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL);
|
const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL);
|
||||||
printf("SDA verified OK (%02hhx:%02hhx)!\n", dac_tlv->value[0], dac_tlv->value[1]);
|
printf("SDA verified OK. (%02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]);
|
||||||
tlvdb_add(tlv, dac_db);
|
tlvdb_add(tlv, dac_db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue