SDA,DDA,fDDA,CDA works

This commit is contained in:
merlokk 2017-12-07 12:42:16 +02:00
commit 66a2d6baf1
4 changed files with 94 additions and 48 deletions

View file

@ -287,6 +287,7 @@ int UsageCmdHFEMVExec(void) {
PrintAndLog(" -v : transaction type - qVSDC or M/Chip.\n");
PrintAndLog(" -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n");
PrintAndLog(" -x : transaction type - VSDC. For test only. Not a standart behavior.\n");
PrintAndLog(" -g : VISA. generate AC from GPO\n");
PrintAndLog("By default : transaction type - MSD.\n");
PrintAndLog("Samples:");
PrintAndLog(" hf emv pse -s -> select card");
@ -302,6 +303,7 @@ int CmdHFEMVExec(const char *cmd) {
bool decodeTLV = false;
bool forceSearch = false;
enum TransactionType TrType = TT_MSD;
bool GenACGPO = false;
uint8_t buf[APDU_RES_LEN] = {0};
size_t len = 0;
@ -355,6 +357,10 @@ int CmdHFEMVExec(const char *cmd) {
case 'C':
TrType = TT_CDA;
break;
case 'g':
case 'G':
GenACGPO = true;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp));
return 1;
@ -425,6 +431,10 @@ int CmdHFEMVExec(const char *cmd) {
PrintAndLog("\n* Init transaction parameters.");
//9F66:(Terminal Transaction Qualifiers (TTQ)) len:4
char *qVSDC = "\x26\x00\x00\x00";
if (GenACGPO) {
qVSDC = "\x26\x80\x00\x00";
}
switch(TrType) {
case TT_MSD:
TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD
@ -434,15 +444,16 @@ int CmdHFEMVExec(const char *cmd) {
TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC
break;
case TT_QVSDCMCHIP:
TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
TLV_ADD(0x9F66, qVSDC); // qVSDC
break;
case TT_CDA:
TLV_ADD(0x9F66, "\x26\x80\x00\x00"); // CDA
TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled)
break;
default:
TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC
break;
}
//9F02:(Amount, Authorised (Numeric)) len:6
TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00");
//9F1A:(Terminal Country Code) len:2
@ -480,7 +491,7 @@ int CmdHFEMVExec(const char *cmd) {
res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot);
free(pdol_data_tlv_data);
//free(pdol_data_tlv);
//free(pdol_data_tlv); --- free on exit.
if (res) {
PrintAndLog("GPO error(%d): %4x. Exit...", res, sw);
@ -695,8 +706,6 @@ int CmdHFEMVExec(const char *cmd) {
// EMVAC_TC + EMVAC_CDAREQ --- to get SDAD
res = EMVAC(true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
//free(cdol_data_tlv);
if (res) {
PrintAndLog("AC1 error(%d): %4x. Exit...", res, sw);
return 5;
@ -713,6 +722,7 @@ int CmdHFEMVExec(const char *cmd) {
PrintAndLog("CDA error (%d)", res);
}
free(ac_tlv);
free(cdol_data_tlv);
PrintAndLog("\n* M/Chip transaction result:");
// 9F27: Cryptogram Information Data (CID)
@ -804,6 +814,7 @@ int CmdHFEMVExec(const char *cmd) {
DropField();
// Destroy TLV's
free(pdol_data_tlv);
tlvdb_free(tlvSelect);
tlvdb_free(tlvRoot);

View file

@ -367,6 +367,44 @@ struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct t
return idn_db;
}
struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, bool showData)
{
size_t data_len;
unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len,
tlvdb_get(db, 0x9f4b, NULL),
tlvdb_get(db, 0x9f37, NULL),
tlvdb_get(db, 0x9f02, NULL),
tlvdb_get(db, 0x5f2a, NULL),
tlvdb_get(db, 0x9f69, NULL),
NULL);
if (!data || data_len < 3)
return NULL;
if (data[3] < 2 || data[3] > data_len - 3) {
free(data);
return NULL;
}
if (showData){
printf("Recovered data:\n");
dump_buffer(data, data_len, stdout, 0);
}
size_t idn_len = data[4];
if (idn_len > data[3] - 1) {
free(data);
return NULL;
}
// 9f36 Application Transaction Counter (ATC)
struct tlvdb *atc_db = tlvdb_fixed(0x9f36, idn_len, data + 5);
free(data);
return atc_db;
}
static bool tlv_hash(void *data, const struct tlv *tlv, int level, bool is_leaf)
{
struct crypto_hash *ch = data;

View file

@ -29,6 +29,7 @@ struct tlvdb *emv_pki_recover_dac(const struct emv_pk *pk, const struct tlvdb *d
struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData);
struct tlvdb *emv_pki_recover_idn(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *dyn_tlv);
struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *dyn_tlv, bool showData);
struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, bool showData);
struct tlvdb *emv_pki_perform_cda(const struct emv_pk *enc_pk, const struct tlvdb *db,
const struct tlvdb *this_db,
const struct tlv *pdol_data_tlv,

View file

@ -532,14 +532,6 @@ int trSDA(struct tlvdb *tlv) {
static const unsigned char default_ddol_value[] = {0x9f, 0x37, 0x04};
static struct tlv default_ddol_tlv = {.tag = 0x9f49, .len = 3, .value = default_ddol_value };
static const unsigned char default_fdda_ddol_value[] =
{0x9f, 0x37, 0x04,
0x9f, 0x02, 0x06,
0x5f, 0x2A, 0x02,
0x9f, 0x69, 0x07, // 9f69[07] Card Authentication Related Data
};
static struct tlv default_fdda_ddol_tlv = {.tag = 0x9f49, .len = 12, .value = default_fdda_ddol_value };
int trDDA(bool decodeTLV, struct tlvdb *tlv) {
uint8_t buf[APDU_RES_LEN] = {0};
size_t len = 0;
@ -608,7 +600,6 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) {
);
}
struct tlvdb *dda_db = NULL;
struct tlv *ddol_data_tlv = NULL;
// 9F4B: Signed Dynamic Application Data
const struct tlv *sdad_tlv = tlvdb_get(tlv, 0x9f4b, NULL);
@ -616,17 +607,30 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) {
// EMV kernel3 v2.4, contactless book C-3, C.1., page 147
if (sdad_tlv) {
PrintAndLog("\n* * Got Signed Dynamic Application Data (9F4B) form GPO. Maybe fDDA...");
dda_db = tlv;
PrintAndLog("\n* Calc fDDA hash");
ddol_data_tlv = dol_process(&default_fdda_ddol_tlv, tlv, 0);
if (!ddol_data_tlv) {
PrintAndLog("ERROR: Can't create fDDA hash TLV");
return 5;
const struct tlvdb *atc_db = emv_pki_recover_atc_ex(icc_pk, tlv, true);
free(ddol_data_tlv);
if (!atc_db) {
PrintAndLog("ERROR: Can't recover IDN (ICC Dynamic Number)");
return 8;
}
PrintAndLog("fDDA hash data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len));
// 9f36 Application Transaction Counter (ATC)
const struct tlv *atc_tlv = tlvdb_get(atc_db, 0x9f36, NULL);
if(atc_tlv) {
PrintAndLog("\nATC (Application Transaction Counter) [%zu] %s", atc_tlv->len, sprint_hex_inrow(atc_tlv->value, atc_tlv->len));
const struct tlv *core_atc_tlv = tlvdb_get(tlv, 0x9f36, NULL);
if(tlv_equal(core_atc_tlv, atc_tlv)) {
PrintAndLog("ATC check OK.");
PrintAndLog("fDDA (fast DDA) verified OK.");
} else {
PrintAndLog("ERROR: fDDA verified, but ATC in the certificate and ATC in the record not the same.");
}
} else {
PrintAndLog("\nERROR: fDDA (fast DDA) verify error");
return 9;
}
} else {
struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv);
if (dac_db) {
@ -660,6 +664,7 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) {
return 6;
}
struct tlvdb *dda_db = NULL;
if (buf[0] == 0x80) {
if (len < 3 ) {
PrintAndLog("ERROR: Internal Authenticate format1 parsing error. length=%d", len);
@ -683,7 +688,6 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) {
if (decodeTLV)
TLVPrintFromTLV(dda_db);
}
}
struct tlvdb *idn_db = emv_pki_recover_idn_ex(icc_pk, dda_db, ddol_data_tlv, true);
free(ddol_data_tlv);
@ -697,24 +701,16 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) {
// 9f4c ICC Dynamic Number
const struct tlv *idn_tlv = tlvdb_get(idn_db, 0x9f4c, NULL);
if(idn_tlv) {
if(sdad_tlv) { // fDDA
PrintAndLog("\nATC (Application Transaction Counter) [%zu] %s", idn_tlv->len, sprint_hex_inrow(idn_tlv->value, idn_tlv->len));
PrintAndLog("fDDA (fast DDA) verified OK.");
} else { // DDA
PrintAndLog("\nIDN (ICC Dynamic Number) [%zu] %s", idn_tlv->len, sprint_hex_inrow(idn_tlv->value, idn_tlv->len));
PrintAndLog("DDA verified OK.");
}
tlvdb_add(tlv, idn_db);
tlvdb_free(idn_db);
} else {
if(sdad_tlv) { // fDDA
PrintAndLog("\nERROR: fDDA (fast DDA) verify error");
} else { // DDA
PrintAndLog("\nERROR: DDA verify error");
}
tlvdb_free(idn_db);
return 9;
}
}
return 0;
}