mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
add 'emv roca' - new command, will be able to test for ROCA
This commit is contained in:
parent
ab9048f7c5
commit
33f6439d38
4 changed files with 97 additions and 11 deletions
|
@ -1382,7 +1382,7 @@ int CmdEMVScan(const char *cmd) {
|
|||
uint8_t SFIend = AFL->value[i * 4 + 2];
|
||||
uint8_t SFIoffline = AFL->value[i * 4 + 3];
|
||||
|
||||
PrintAndLog("--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
|
||||
PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline);
|
||||
if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) {
|
||||
PrintAndLogEx(ERR, "SFI ERROR! Skipped...");
|
||||
continue;
|
||||
|
@ -1476,6 +1476,89 @@ int CmdEMVTest(const char *cmd) {
|
|||
return ExecuteCryptoTests(true);
|
||||
}
|
||||
|
||||
int CmdEMVRoca(const char *cmd) {
|
||||
|
||||
CLIParserInit("emv roca",
|
||||
"Tries to extract public keys and run the ROCA test against them.\n",
|
||||
"Usage:\n\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n");
|
||||
|
||||
void* argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(cmd, argtable, true);
|
||||
|
||||
EMVCommandChannel channel = ECC_CONTACTLESS;
|
||||
if (arg_get_lit(1))
|
||||
channel = ECC_CONTACT;
|
||||
|
||||
// Init TLV tree
|
||||
const char *alr = "Root terminal TLV tree";
|
||||
struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr);
|
||||
|
||||
|
||||
|
||||
int res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot);
|
||||
|
||||
// getting certificates
|
||||
if (tlvdb_get(tlvRoot, 0x90, NULL)) {
|
||||
PrintAndLogEx(INFO, "-->Recovering certificates.");
|
||||
PKISetStrictExecution(false);
|
||||
|
||||
struct emv_pk *pk = get_ca_pk(tlvRoot);
|
||||
if (!pk) {
|
||||
PrintAndLogEx(ERR, "ERROR: Key not found. Exit.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot);
|
||||
if (!issuer_pk) {
|
||||
emv_pk_free(pk);
|
||||
PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %s IDX %02hhx CSN %s",
|
||||
sprint_hex(issuer_pk->rid, 5),
|
||||
issuer_pk->index,
|
||||
sprint_hex(issuer_pk->serial, 3)
|
||||
);
|
||||
|
||||
|
||||
struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, NULL);
|
||||
if (!icc_pk) {
|
||||
emv_pk_free(pk);
|
||||
emv_pk_free(issuer_pk);
|
||||
PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit.");
|
||||
goto out;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %s IDX %02hhx CSN %s\n",
|
||||
sprint_hex(icc_pk->rid, 5),
|
||||
icc_pk->index,
|
||||
sprint_hex(icc_pk->serial, 3)
|
||||
);
|
||||
|
||||
// icc_pk->exp, icc_pk->elen
|
||||
// icc_pk->modulus, icc_pk->mlen
|
||||
|
||||
|
||||
PKISetStrictExecution(true);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
// free tlv object
|
||||
tlvdb_free(tlvRoot);
|
||||
|
||||
if ( channel == ECC_CONTACTLESS)
|
||||
DropField();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"exec", CmdEMVExec, 0, "Executes EMV contactless transaction."},
|
||||
|
@ -1497,6 +1580,7 @@ static command_t CommandTable[] = {
|
|||
{"clone", CmdEmvClone, 0, "clone an EMV tag"},
|
||||
*/
|
||||
{"list", CmdEMVList, 0, "[Deprecated] List ISO7816 history"},
|
||||
{"roca", CmdEMVRoca, 0, "Extract public keys and run ROCA test"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -34,5 +34,6 @@ extern int CmdEMVPPSE(const char *cmd);
|
|||
extern int CmdEMVExec(const char *cmd);
|
||||
extern int CmdEMVGetrng(const char *Cmd);
|
||||
extern int CmdEMVList(const char *Cmd);
|
||||
extern int CmdEMVRoca(const char *Cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -519,7 +519,7 @@ int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8
|
|||
}
|
||||
|
||||
// Authentication
|
||||
static struct emv_pk *get_ca_pk(struct tlvdb *db) {
|
||||
struct emv_pk *get_ca_pk(struct tlvdb *db) {
|
||||
const struct tlv *df_tlv = tlvdb_get(db, 0x84, NULL);
|
||||
const struct tlv *caidx_tlv = tlvdb_get(db, 0x8f, NULL);
|
||||
|
||||
|
@ -900,7 +900,7 @@ int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) {
|
|||
PrintAndLog("WARNING: Issuer certificate not found. Exit.");
|
||||
return 2;
|
||||
}
|
||||
PrintAndLog("Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx",
|
||||
PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx",
|
||||
issuer_pk->rid[0],
|
||||
issuer_pk->rid[1],
|
||||
issuer_pk->rid[2],
|
||||
|
@ -923,10 +923,10 @@ int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) {
|
|||
if (!icc_pk) {
|
||||
emv_pk_free(pk);
|
||||
emv_pk_free(issuer_pk);
|
||||
PrintAndLog("WARNING: ICC certificate not found. Exit.");
|
||||
PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit.");
|
||||
return 2;
|
||||
}
|
||||
printf("ICC PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n",
|
||||
PrintAndLogEx(SUCCESS, "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],
|
||||
|
|
|
@ -102,6 +102,7 @@ extern int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_
|
|||
|
||||
extern int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root);
|
||||
|
||||
extern struct emv_pk *get_ca_pk(struct tlvdb *db);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue