mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
commit
cbfa764c99
4 changed files with 260 additions and 56 deletions
|
@ -330,7 +330,7 @@ void CIPURSEPrintInfoFile(uint8_t *data, size_t len) {
|
|||
CIPURSEPrintManufacturerInfo(data[8]);
|
||||
}
|
||||
|
||||
static void CIPURSEPrintFileDescriptor(uint8_t desc) {
|
||||
void CIPURSEPrintFileDescriptor(uint8_t desc) {
|
||||
if (desc == 0x01)
|
||||
PrintAndLogEx(INFO, "Binary file");
|
||||
else if (desc == 0x11)
|
||||
|
|
|
@ -61,5 +61,6 @@ bool CIPURSEChannelAuthenticate(uint8_t keyindex, uint8_t *key, bool verbose);
|
|||
void CIPURSECSetActChannelSecurityLevels(CipurseChannelSecurityLevel req, CipurseChannelSecurityLevel resp);
|
||||
|
||||
void CIPURSEPrintFileAttr(uint8_t *attr, size_t len);
|
||||
void CIPURSEPrintFileDescriptor(uint8_t desc);
|
||||
|
||||
#endif /* __CIPURSECORE_H__ */
|
||||
|
|
|
@ -82,6 +82,28 @@ static uint16_t defaultFileId = 0x2ff7;
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int SelectAndPrintInfoFile(void) {
|
||||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
|
||||
int res = CIPURSESelectFile(0x2ff7, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000)
|
||||
return PM3_EAPDU_FAIL;
|
||||
|
||||
res = CIPURSEReadBinary(0, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000)
|
||||
return PM3_EAPDU_FAIL;
|
||||
|
||||
if (len > 0) {
|
||||
PrintAndLogEx(INFO, "Info file ( " _GREEN_("ok") " )");
|
||||
PrintAndLogEx(INFO, "[%zu]: %s", len, sprint_hex(buf, len));
|
||||
CIPURSEPrintInfoFile(buf, len);
|
||||
PrintAndLogEx(INFO, "");
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHFCipurseInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cipurse info",
|
||||
|
@ -107,10 +129,14 @@ static int CmdHFCipurseInfo(const char *Cmd) {
|
|||
uint16_t sw = 0;
|
||||
|
||||
bool mfExist = false;
|
||||
bool infoPrinted = false;
|
||||
int res = CIPURSESelectMFEx(true, true, buf, sizeof(buf), &len, &sw);
|
||||
if (res == PM3_SUCCESS && sw == 0x9000) {
|
||||
mfExist = true;
|
||||
PrintAndLogEx(INFO, _CYAN_("MasterFile") " exist and can be selected.");
|
||||
|
||||
res = SelectAndPrintInfoFile();
|
||||
infoPrinted = (res == PM3_SUCCESS);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAYLEN(PxSE_AID_LIST); i++) {
|
||||
|
@ -122,6 +148,7 @@ static int CmdHFCipurseInfo(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "PxSE data:");
|
||||
TLVPrintFromBuffer(buf, len);
|
||||
}
|
||||
PrintAndLogEx(INFO, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +157,7 @@ static int CmdHFCipurseInfo(const char *Cmd) {
|
|||
DropField();
|
||||
return res;
|
||||
}
|
||||
PrintAndLogEx(INFO, "Application `AF F1` selected " _GREEN_("successfully"));
|
||||
|
||||
if (sw != 0x9000) {
|
||||
if (sw == 0x0000) {
|
||||
|
@ -147,30 +175,21 @@ static int CmdHFCipurseInfo(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "Cipurse card ( " _GREEN_("ok") " )");
|
||||
|
||||
res = CIPURSESelectFile(0x2ff7, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
DropField();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
res = CIPURSEReadBinary(0, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
DropField();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
PrintAndLogEx(INFO, "Info file ( " _GREEN_("ok") " )");
|
||||
PrintAndLogEx(INFO, "[%zu]: %s", len, sprint_hex(buf, len));
|
||||
CIPURSEPrintInfoFile(buf, len);
|
||||
if (!infoPrinted) {
|
||||
res = SelectAndPrintInfoFile();
|
||||
if (res != PM3_SUCCESS) {
|
||||
DropField();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
DropField();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CLIParseCommandParameters(CLIParserContext *ctx, size_t keyid, size_t aidid, size_t fidid, size_t sreqid, size_t srespid,
|
||||
uint8_t *key, uint8_t *aid, size_t *aidlen, bool *useaid, uint16_t *fid, bool *usefid, CipurseChannelSecurityLevel *sreq, CipurseChannelSecurityLevel *sresp) {
|
||||
static int CLIParseCommandParametersEx(CLIParserContext *ctx, size_t keyid, size_t aidid, size_t fidid, size_t chfidid, size_t sreqid, size_t srespid,
|
||||
uint8_t *key, uint8_t *aid, size_t *aidlen, bool *useaid, uint16_t *fid, bool *usefid, uint16_t *chfid, bool *usechfid,
|
||||
CipurseChannelSecurityLevel *sreq, CipurseChannelSecurityLevel *sresp) {
|
||||
uint8_t hdata[250] = {0};
|
||||
int hdatalen = sizeof(hdata);
|
||||
if (keyid) {
|
||||
|
@ -219,7 +238,7 @@ static int CLIParseCommandParameters(CLIParserContext *ctx, size_t keyid, size_t
|
|||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
*fid = defaultFileId;
|
||||
*fid = 0;
|
||||
if (hdatalen) {
|
||||
*fid = (hdata[0] << 8) + hdata[1];
|
||||
if (usefid)
|
||||
|
@ -227,6 +246,24 @@ static int CLIParseCommandParameters(CLIParserContext *ctx, size_t keyid, size_t
|
|||
}
|
||||
}
|
||||
|
||||
if (usechfid)
|
||||
*usechfid = false;
|
||||
if (chfidid && chfid) {
|
||||
hdatalen = sizeof(hdata);
|
||||
CLIGetHexWithReturn(ctx, chfidid, hdata, &hdatalen);
|
||||
if (hdatalen && hdatalen != 2) {
|
||||
PrintAndLogEx(ERR, _RED_("ERROR:") " child file id length must be 2 bytes only");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
*chfid = defaultFileId;
|
||||
if (hdatalen) {
|
||||
*chfid = (hdata[0] << 8) + hdata[1];
|
||||
if (usechfid)
|
||||
*usechfid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sreqid && srespid && sreq && sresp) {
|
||||
*sreq = CPSMACed;
|
||||
*sresp = CPSMACed;
|
||||
|
@ -275,9 +312,19 @@ static int CLIParseCommandParameters(CLIParserContext *ctx, size_t keyid, size_t
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int SelectCommand(bool selectDefaultFile, bool useAID, uint8_t *aid, size_t aidLen, bool useFID, uint16_t fileId, bool verbose,
|
||||
static int CLIParseCommandParameters(CLIParserContext *ctx, size_t keyid, size_t aidid, size_t fidid, size_t sreqid, size_t srespid,
|
||||
uint8_t *key, uint8_t *aid, size_t *aidlen, bool *useaid, uint16_t *fid, bool *usefid,
|
||||
CipurseChannelSecurityLevel *sreq, CipurseChannelSecurityLevel *sresp) {
|
||||
return CLIParseCommandParametersEx(ctx, keyid, aidid, fidid, 0, sreqid, srespid,
|
||||
key, aid, aidlen, useaid, fid, usefid, NULL, NULL, sreq, sresp);
|
||||
}
|
||||
|
||||
static int SelectCommandEx(bool selectDefaultFile, bool useAID, uint8_t *aid, size_t aidLen, bool useFID, uint16_t fileId,
|
||||
bool selChildFile, uint16_t childFileId, bool verbose,
|
||||
uint8_t *buf, size_t bufSize, size_t *len, uint16_t *sw) {
|
||||
int res = 0;
|
||||
if (verbose && selChildFile)
|
||||
PrintAndLogEx(INFO, "Select top level application/file");
|
||||
if (useAID && aidLen > 0) {
|
||||
res = CIPURSESelectAID(true, true, aid, aidLen, buf, bufSize, len, sw);
|
||||
if (res != 0 || *sw != 0x9000) {
|
||||
|
@ -316,9 +363,27 @@ static int SelectCommand(bool selectDefaultFile, bool useAID, uint8_t *aid, size
|
|||
PrintAndLogEx(INFO, "Cipurse select default application " _GREEN_("OK"));
|
||||
}
|
||||
|
||||
if (selChildFile) {
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Select child file");
|
||||
|
||||
res = CIPURSESelectFileEx(false, true, childFileId, buf, bufSize, len, sw);
|
||||
if (res != 0 || *sw != 0x9000) {
|
||||
if (verbose)
|
||||
PrintAndLogEx(ERR, "Select child file 0x%04x " _RED_("error") ". Card returns 0x%04x", childFileId, *sw);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Select child file " _CYAN_("0x%04x ") _GREEN_("OK"), childFileId);
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int SelectCommand(bool selectDefaultFile, bool useAID, uint8_t *aid, size_t aidLen, bool useFID, uint16_t fileId, bool verbose,
|
||||
uint8_t *buf, size_t bufSize, size_t *len, uint16_t *sw) {
|
||||
return SelectCommandEx(selectDefaultFile, useAID, aid, aidLen, useFID, fileId, false, 0, verbose, buf, bufSize, len, sw);
|
||||
}
|
||||
|
||||
static int CmdHFCipurseSelect(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
|
@ -335,8 +400,9 @@ static int CmdHFCipurseSelect(const char *Cmd) {
|
|||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_lit0("t", "tlv", "TLV decode returned data"),
|
||||
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"),
|
||||
arg_str0(NULL, "fid", "<hex 2 bytes>", "file ID (FID)"),
|
||||
arg_str0(NULL, "fid", "<hex 2 bytes>", "top level file (or application) ID (FID)"),
|
||||
arg_lit0(NULL, "mfd", "select masterfile by empty id"),
|
||||
arg_str0(NULL, "chfid", "<hex 2 bytes>", "child file ID (EF under application/master file)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -348,9 +414,11 @@ static int CmdHFCipurseSelect(const char *Cmd) {
|
|||
uint8_t aid[16] = {0};
|
||||
size_t aidLen = 0;
|
||||
bool useAID = false;
|
||||
uint16_t fileId = defaultFileId;
|
||||
uint16_t fileId = 0;
|
||||
bool useFID = false;
|
||||
int res = CLIParseCommandParameters(ctx, 0, 4, 5, 0, 0, NULL, aid, &aidLen, &useAID, &fileId, &useFID, NULL, NULL);
|
||||
uint16_t childFileId = defaultFileId;
|
||||
bool useChildFID = false;
|
||||
int res = CLIParseCommandParametersEx(ctx, 0, 4, 5, 7, 0, 0, NULL, aid, &aidLen, &useAID, &fileId, &useFID, &childFileId, &useChildFID, NULL, NULL);
|
||||
if (res || (useAID && useFID)) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
|
@ -365,7 +433,7 @@ static int CmdHFCipurseSelect(const char *Cmd) {
|
|||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
res = SelectCommand(selmfd, useAID, aid, aidLen, useFID, fileId, true, buf, sizeof(buf), &len, &sw);
|
||||
res = SelectCommandEx(selmfd, useAID, aid, aidLen, useFID, fileId, useChildFID, childFileId, true, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
|
@ -397,7 +465,7 @@ static int CmdHFCipurseAuth(const char *Cmd) {
|
|||
arg_lit0("a", "apdu", "show APDU requests and responses"),
|
||||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"),
|
||||
arg_str0(NULL, "fid", "<hex 2 bytes>", "file ID (FID)"),
|
||||
arg_str0(NULL, "fid", "<hex 2 bytes>", "top file/application ID (FID)"),
|
||||
arg_lit0(NULL, "mfd", "select masterfile by empty id"),
|
||||
arg_int0("n", NULL, "<dec>", "key ID"),
|
||||
arg_str0("k", "key", "<hex>", "Auth key"),
|
||||
|
@ -887,7 +955,8 @@ static int CmdHFCipurseCreateDGI(const char *Cmd) {
|
|||
"Create application/file/key by provide appropriate DGI. If no key is supplied, default key of 737373...7373 will be used",
|
||||
"hf cipurse create -d 9200123F00200008000062098407A0000005070100 -> create PTSE file with FID 0x2000 and space for 8 AIDs\n"
|
||||
"hf cipurse create -d 92002438613F010A050200004040FF021009021009621084054144204631D407A0000005070100A00F28"
|
||||
"73737373737373737373737373737373015FD67B000102030405060708090A0B0C0D0E0F01C6A13B -> create default file with FID 3F01 and 2 keys\n");
|
||||
"73737373737373737373737373737373015FD67B000102030405060708090A0B0C0D0E0F01C6A13B -> create default file with FID 3F01 and 2 keys\n"
|
||||
"hf cipurse create --aid 4144204631 -d 92010C010001020030020000FFFFFF -> create 0x0102 binary data EF under application 4144204631\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -895,11 +964,16 @@ static int CmdHFCipurseCreateDGI(const char *Cmd) {
|
|||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_int0("n", NULL, "<dec>", "key ID"),
|
||||
arg_str0("k", "key", "<hex>", "Auth key"),
|
||||
|
||||
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"),
|
||||
arg_str0(NULL, "fid", "<hex 2 bytes>", "file ID (FID)"),
|
||||
arg_lit0(NULL, "mfd", "select masterfile by empty id"),
|
||||
|
||||
arg_str0("d", "data", "<hex>", "data with DGI for create"),
|
||||
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"),
|
||||
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"),
|
||||
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
||||
arg_lit0(NULL, "commit", "commit "),
|
||||
arg_lit0(NULL, "commit", "need commit after create"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
@ -912,38 +986,65 @@ static int CmdHFCipurseCreateDGI(const char *Cmd) {
|
|||
CipurseChannelSecurityLevel sresp = CPSMACed;
|
||||
uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0};
|
||||
|
||||
uint8_t aid[16] = {0};
|
||||
size_t aidLen = 0;
|
||||
bool useAID = false;
|
||||
uint16_t fileId = defaultFileId;
|
||||
bool useFID = false;
|
||||
int res = CLIParseCommandParameters(ctx, 4, 0, 0, 6, 7, key, NULL, NULL, NULL, &fileId, &useFID, &sreq, &sresp);
|
||||
int res = CLIParseCommandParameters(ctx, 4, 5, 6, 9, 10, key, aid, &aidLen, &useAID, &fileId, &useFID, &sreq, &sresp);
|
||||
if (res) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool selmfd = arg_get_lit(ctx, 7);
|
||||
|
||||
uint8_t hdata[250] = {0};
|
||||
int hdatalen = sizeof(hdata);
|
||||
CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen);
|
||||
CLIGetHexWithReturn(ctx, 8, hdata, &hdatalen);
|
||||
if (hdatalen < 4 || hdatalen > 200) {
|
||||
PrintAndLogEx(ERR, _RED_("ERROR:") " data length must be 4-200 bytes only");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool noauth = arg_get_lit(ctx, 8);
|
||||
bool needCommit = arg_get_lit(ctx, 9);
|
||||
bool noauth = arg_get_lit(ctx, 11);
|
||||
bool needCommit = arg_get_lit(ctx, 12);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
SetAPDULogging(APDULogging);
|
||||
|
||||
if (verbose && hdatalen > 3) {
|
||||
if (hdata[0] == 0x92 && hdata[1] == 0x00)
|
||||
PrintAndLogEx(INFO, "DGI 9200 - ADF file attributes");
|
||||
if (hdata[0] == 0x92 && hdata[1] == 0x01) {
|
||||
PrintAndLogEx(INFO, "DGI 9201 - EF file attributes");
|
||||
PrintAndLogEx(INFO, "File type:");
|
||||
CIPURSEPrintFileDescriptor(hdata[3]);
|
||||
}
|
||||
if (hdata[0] == 0xa0 && hdata[1] == 0x0f)
|
||||
PrintAndLogEx(INFO, "DGI a00f - All key values");
|
||||
}
|
||||
|
||||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
|
||||
res = CIPURSESelectMFEx(true, true, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Cipurse masterfile select " _RED_("error") ". Card returns 0x%04x", sw);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
if (useAID || useFID || selmfd) {
|
||||
res = SelectCommand(selmfd, useAID, aid, aidLen, useFID, fileId, verbose, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
} else {
|
||||
res = CIPURSESelectMFEx(true, true, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Cipurse masterfile select " _RED_("error") ". Card returns 0x%04x", sw);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Cipurse masterfile " _GREEN_("selected"));
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
|
@ -981,6 +1082,9 @@ static int CmdHFCipurseCreateDGI(const char *Cmd) {
|
|||
res = CIPURSECommitTransaction(&sw);
|
||||
if (res != 0 || sw != 0x9000)
|
||||
PrintAndLogEx(WARNING, "Commit " _YELLOW_("ERROR") ". Card returns 0x%04x", sw);
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Commit " _GREEN_("OK"));
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
@ -991,9 +1095,10 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
|
|||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf cipurse delete",
|
||||
"Delete file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
|
||||
"hf cipurse delete --fid 2ff7 -> Authenticate with keyID 1, delete file with id 2ff7\n"
|
||||
"hf cipurse delete --fid 2ff7 -> Authenticate with keyID 1, delete file with id 2ff7 at top level\n"
|
||||
"hf cipurse delete -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and delete file\n"
|
||||
"hf cipurse delete --aid --no-auth -> delete PTSE file with AID A0000005070100 without authentication\n");
|
||||
"hf cipurse delete --aid A0000005070100 --no-auth -> delete PTSE file with AID A0000005070100 without authentication\n"
|
||||
"hf cipurse delete --aid 4144204631 --chfid 0102 -> delete EF with FID 0x0102 under default application\n");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -1001,8 +1106,9 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
|
|||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_int0("n", NULL, "<dec>", "key ID"),
|
||||
arg_str0("k", "key", "<hex>", "Auth key"),
|
||||
arg_str0(NULL, "fid", "<hex>", "file ID for delete"),
|
||||
arg_str0(NULL, "fid", "<hex>", "file/application ID under MF for delete"),
|
||||
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID) for delete"),
|
||||
arg_str0(NULL, "chfid", "<hex 2 bytes>", "child file ID (EF under application/master file)"),
|
||||
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"),
|
||||
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"),
|
||||
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
||||
|
@ -1024,36 +1130,30 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
|
|||
bool useAID = false;
|
||||
uint16_t fileId = defaultFileId;
|
||||
bool useFID = false;
|
||||
int res = CLIParseCommandParameters(ctx, 4, 6, 5, 7, 8, key, aid, &aidLen, &useAID, &fileId, &useFID, &sreq, &sresp);
|
||||
uint16_t childFileId = defaultFileId;
|
||||
bool useChildFID = false;
|
||||
int res = CLIParseCommandParametersEx(ctx, 4, 6, 5, 7, 8, 9, key, aid, &aidLen, &useAID, &fileId, &useFID, &childFileId, &useChildFID, &sreq, &sresp);
|
||||
// useAID and useFID in the same state
|
||||
if (res || !(useAID ^ useFID)) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool noauth = arg_get_lit(ctx, 9);
|
||||
bool needCommit = arg_get_lit(ctx, 10);
|
||||
bool noauth = arg_get_lit(ctx, 10);
|
||||
bool needCommit = arg_get_lit(ctx, 11);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
SetAPDULogging(APDULogging);
|
||||
|
||||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
|
||||
res = CIPURSESelectMFEx(true, true, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Cipurse masterfile select " _RED_("error") ". Card returns 0x%04x", sw);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
if (useFID)
|
||||
PrintAndLogEx(INFO, "File id " _CYAN_("%x"), fileId);
|
||||
else
|
||||
PrintAndLogEx(INFO, "Application ID " _CYAN_("%s"), sprint_hex_inrow(aid, aidLen));
|
||||
|
||||
if (useChildFID)
|
||||
PrintAndLogEx(INFO, "Child file id " _CYAN_("%x"), childFileId);
|
||||
|
||||
if (!noauth)
|
||||
PrintAndLogEx(INFO, "key id " _YELLOW_("%d") " key " _YELLOW_("%s")
|
||||
, keyId
|
||||
|
@ -1061,6 +1161,26 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
|
|||
);
|
||||
}
|
||||
|
||||
uint8_t buf[APDU_RES_LEN] = {0};
|
||||
size_t len = 0;
|
||||
uint16_t sw = 0;
|
||||
|
||||
if (useChildFID) {
|
||||
res = SelectCommand(false, useAID, aid, aidLen, useFID, fileId, verbose, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Top level select " _RED_("error") ". Card returns 0x%04x", sw);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
} else {
|
||||
res = CIPURSESelectMFEx(true, true, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Cipurse masterfile select " _RED_("error") ". Card returns 0x%04x", sw);
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!noauth) {
|
||||
bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose);
|
||||
if (bres == false) {
|
||||
|
@ -1074,7 +1194,16 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
|
|||
CIPURSECSetActChannelSecurityLevels(sreq, sresp);
|
||||
}
|
||||
|
||||
if (useFID) {
|
||||
if (useChildFID) {
|
||||
res = CIPURSEDeleteFile(childFileId, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Delete child file " _CYAN_("%04x ") _RED_("ERROR") ". Card returns:\n 0x%04x - %s", childFileId, sw,
|
||||
GetSpecificAPDUCodeDesc(DeleteAPDUCodeDescriptions, ARRAYLEN(DeleteAPDUCodeDescriptions), sw));
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
PrintAndLogEx(INFO, "Child file id " _CYAN_("%04x") " deleted " _GREEN_("succesfully"), childFileId);
|
||||
} else if (useFID) {
|
||||
res = CIPURSEDeleteFile(fileId, buf, sizeof(buf), &len, &sw);
|
||||
if (res != 0 || sw != 0x9000) {
|
||||
PrintAndLogEx(ERR, "Delete file " _CYAN_("%04x ") _RED_("ERROR") ". Card returns:\n 0x%04x - %s", fileId, sw,
|
||||
|
@ -1101,6 +1230,9 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
|
|||
res = CIPURSECommitTransaction(&sw);
|
||||
if (res != 0 || sw != 0x9000)
|
||||
PrintAndLogEx(WARNING, "Commit " _YELLOW_("ERROR") ". Card returns 0x%04x", sw);
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Commit " _GREEN_("OK"));
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
- [Source code](#source-code)
|
||||
- [Communication channel with a card](#communication-channel-with-a-card)
|
||||
- [Card architecture](#card-architecture)
|
||||
- [Card structure](#card-structure)
|
||||
- [How to](#how-to)
|
||||
- [How to personalize card](#how-to-personalize-card)
|
||||
|
||||
|
@ -42,6 +43,7 @@ After authentication reader can specify the mode for each channel for each comma
|
|||
|
||||
Card answers if the mode that sets by the reader matches the mode of the file and the command matches the key via an access list.
|
||||
|
||||
|
||||
## Card architecture
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -55,6 +57,28 @@ Master file have keys and an access control list that works at the card level.
|
|||
|
||||
Each file can only have an access control list that specifies what operation the key can do with this file.
|
||||
|
||||
Card have transaction mechanism. Transaction not needs for control structure at application level and to change files without
|
||||
transaction mechanism. All the rest changes needs to issue COMMIT command (`--commit` key)
|
||||
|
||||
## Card structure
|
||||
^[Top](#top)
|
||||
|
||||
- Master file (MF)
|
||||
- Keys
|
||||
- Group security levels and access rights
|
||||
- files under master file (EF). Usually have no access to them.
|
||||
|
||||
- PxSE files (directory files)
|
||||
|
||||
- Application 1. Have AID (up to 16-bytes) and FID (2-bytes id)
|
||||
-- Application keys
|
||||
-- Group security levels and access rights
|
||||
-- Application files (EF). Have type (1-byte) and FID ((2-bytes id))
|
||||
|
||||
- Application 2
|
||||
- ...
|
||||
|
||||
|
||||
## How to
|
||||
|
||||
### How to select application or file
|
||||
|
@ -78,6 +102,24 @@ select it with display output in raw and tlv views options
|
|||
5. select default file (usually it master file)
|
||||
```hf cipurse select --mfd```
|
||||
|
||||
|
||||
### How to delete application or file
|
||||
^[Top](#top)
|
||||
|
||||
1. delete PTSE by AID
|
||||
```hf cipurse delete --aid a0000005070100```
|
||||
|
||||
2. delete application by AID
|
||||
```hf cipurse delete --aid 4144204631```
|
||||
|
||||
3. delete application/top level file by FID
|
||||
```hf cipurse delete --fid 2000```
|
||||
|
||||
3. delete file by FID from default application `AD F1`
|
||||
|
||||
```hf cipurse delete --aid 4144204631 --chfid 0102```
|
||||
|
||||
|
||||
### How to personalize card
|
||||
^[Top](#top)
|
||||
|
||||
|
@ -108,7 +150,7 @@ This command creates a application with following details:
|
|||
- App type............... 61
|
||||
- Max files count........ 10
|
||||
- Max SFID count......... 5
|
||||
- Minimum command's group security levels plain/plain/plain/plain (0000)
|
||||
- Minimum command's group security levels: plain/plain/plain/plain (0000)
|
||||
- Access rights.......... all two keys can do anything (FFFFFF)
|
||||
- Key attributes......... 021009
|
||||
- 2 keys.........
|
||||
|
@ -116,3 +158,32 @@ This command creates a application with following details:
|
|||
- `0001..0e0f` (01/C6A13B)
|
||||
- Register in the PxSE... A0000005070100
|
||||
|
||||
4. Create elementary file(s) (EF) inside the application
|
||||
|
||||
```hf cipurse create --aid 4144204631 -d 92010C010001020030020000FFFFFF --commit```
|
||||
|
||||
```
|
||||
- parent application ID.. 4144204631
|
||||
- file type.............. 0x01 (binary file wo transaction)
|
||||
- SFID................... 0x00
|
||||
- FID.................... 0x0102
|
||||
- File size.............. 0x0030 (48 bytes)
|
||||
- Number of keys......... 0x02 (as in the parent application)
|
||||
- Minimum command's group security levels: plain/plain/plain/plain (0000)
|
||||
- Access rights.......... all two keys can do anything (FFFFFF)
|
||||
```
|
||||
|
||||
5. Save data to elementary file(s) (EF)
|
||||
|
||||
```hf cipurse write --fid 0102 -d 010203040506070809```
|
||||
|
||||
or if file with transaction mechanism
|
||||
|
||||
|
||||
```hf cipurse write --fid 0102 -d 010203040506070809 --commit```
|
||||
|
||||
|
||||
6. Check file(s) contents (if needs)
|
||||
```hf cipurse read --fid 0102```
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue