SDA works

This commit is contained in:
merlokk 2017-12-05 18:13:32 +02:00
commit 667a1beafb
3 changed files with 48 additions and 22 deletions

View file

@ -308,6 +308,8 @@ int CmdHFEMVExec(const char *cmd) {
uint16_t sw = 0;
uint8_t AID[APDU_AID_LEN] = {0};
size_t AIDlen = 0;
uint8_t ODAiList[4096];
size_t ODAiListLen = 0;
int res;
@ -568,9 +570,23 @@ int CmdHFEMVExec(const char *cmd) {
PrintAndLog("");
}
// Build Input list for Offline Data Authentication
// EMV 4.3 book3 10.3, page 96
if (SFIoffline) {
// here will be offline records storing...
// dont foget: if (sfi < 11)
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;
}
// 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
const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL);
uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100;

View file

@ -177,7 +177,7 @@ static const struct emv_tag emv_tags[] = {
{ 0x01 , "", EMV_TAG_STRING }, // string for headers
{ 0x02 , "Raw data", }, // data
{ 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
{ 0x41 , "Country code and national data" },

View file

@ -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);
if (!issuer_pk) {
PrintAndLog("ERROR: Issuer certificate found. Exit.");
PrintAndLog("ERROR: Issuer certificate not found. Exit.");
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);
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;
}
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
if (dac_db) {
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);
} else {
PrintAndLog("ERROR: SSAD verify error");
@ -538,13 +538,16 @@ int trDDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
const struct tlv *sda_tlv = tlvdb_get(tlv, 0x21, NULL);
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;
}
struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv);
if (issuer_pk)
printf("Issuer PK recovered! RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
if (!issuer_pk) {
PrintAndLog("ERROR: Issuer certificate not found. Exit.");
return 2;
}
printf("Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
issuer_pk->rid[0],
issuer_pk->rid[1],
issuer_pk->rid[2],
@ -558,7 +561,7 @@ int trDDA(uint8_t *AID, size_t AIDlen, struct tlvdb *tlv) {
struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv);
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[1],
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);
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[1],
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);
if (dac_db) {
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);
}