card format command and create file sketch

This commit is contained in:
merlokk 2022-01-28 19:35:14 +02:00
parent 9ef78cfbe7
commit 1b15811c5f
3 changed files with 221 additions and 3 deletions

View file

@ -172,6 +172,12 @@ int CIPURSESelectMF(uint8_t *result, size_t max_result_len, size_t *result_len,
return CIPURSESelectMFEx(false, true, result, max_result_len, result_len, sw); return CIPURSESelectMFEx(false, true, result, max_result_len, result_len, sw);
} }
int CIPURSEFormatAll(uint16_t *sw) {
uint8_t result[APDU_RES_LEN] = {0};
size_t result_len = 0;
return CIPURSEExchange((sAPDU_t) {0x80, 0xfc, 0x00, 0x00, 7, (uint8_t *)"ConfirM"}, result, sizeof(result), &result_len, sw);
}
int CIPURSESelectFileEx(bool activate_field, bool leave_field_on, uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { int CIPURSESelectFileEx(bool activate_field, bool leave_field_on, uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) {
CipurseCClearContext(&cipurseContext); CipurseCClearContext(&cipurseContext);
uint8_t fileIdBin[] = {fileid >> 8, fileid & 0xff}; uint8_t fileIdBin[] = {fileid >> 8, fileid & 0xff};

View file

@ -40,6 +40,8 @@ int CIPURSECreateFile(uint8_t *attr, uint16_t attrlen, uint8_t *result, size_t m
int CIPURSEDeleteFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); int CIPURSEDeleteFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw);
int CIPURSEDeleteFileAID(uint8_t *aid, size_t aidLen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); int CIPURSEDeleteFileAID(uint8_t *aid, size_t aidLen, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw);
int CIPURSEFormatAll(uint16_t *sw);
int CIPURSESelectFileEx(bool activate_field, bool leave_field_on, uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); int CIPURSESelectFileEx(bool activate_field, bool leave_field_on, uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw);
int CIPURSESelectFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); int CIPURSESelectFile(uint16_t fileid, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw);
int CIPURSESelectMFDefaultFileEx(bool activate_field, bool leave_field_on, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw); int CIPURSESelectMFDefaultFileEx(bool activate_field, bool leave_field_on, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw);

View file

@ -767,8 +767,216 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHFCipurseCreateDGI(const char *Cmd) { static int CmdHFCipurseFormatAll(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf cipurse formatall",
"Format card. Erases all the data at the card level!",
"hf cipurse formatall -> Format card with default key\n"
"hf cipurse formatall -n 2 -k 65656565656565656565656565656565 -> Format card with keyID 2\n"
"hf cipurse formatall --no-auth -> Format card without authentication. Works for card in perso state\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"),
arg_int0("n", NULL, "<dec>", "key ID"),
arg_str0("k", "key", "<hex>", "Auth key"),
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_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool APDULogging = arg_get_lit(ctx, 1);
bool verbose = arg_get_lit(ctx, 2);
uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId);
CipurseChannelSecurityLevel sreq = CPSMACed;
CipurseChannelSecurityLevel sresp = CPSMACed;
uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0};
int res = CLIParseKeyAndSecurityLevels(ctx, 4, 5, 6, key, &sreq, &sresp);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool noauth = arg_get_lit(ctx, 7);
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) {
PrintAndLogEx(WARNING, _YELLOW_("FORMAT erases all the data at this card!!!"));
if (!noauth)
PrintAndLogEx(INFO, "key id " _YELLOW_("%d") " key " _YELLOW_("%s")
, keyId
, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)
);
}
if (!noauth) {
bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose);
if (bres == false) {
if (verbose)
PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )");
DropField();
return PM3_ESOFT;
}
// set channel security levels
CIPURSECSetActChannelSecurityLevels(sreq, sresp);
}
res = CIPURSEFormatAll(&sw);
if (res != 0 || sw != 0x9000) {
PrintAndLogEx(ERR, "Format " _RED_("ERROR") ". Card returns 0x%04x", sw);
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "Card formatted " _GREEN_("succesfully"));
DropField();
return PM3_SUCCESS;
}
static int CmdHFCipurseCreateDGI(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf cipurse create",
"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 -> create default file with FID 5F00\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"),
arg_int0("n", NULL, "<dec>", "key ID"),
arg_str0("k", "key", "<hex>", "Auth key"),
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_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool APDULogging = arg_get_lit(ctx, 1);
bool verbose = arg_get_lit(ctx, 2);
uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId);
CipurseChannelSecurityLevel sreq = CPSMACed;
CipurseChannelSecurityLevel sresp = CPSMACed;
uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0};
int res = CLIParseKeyAndSecurityLevels(ctx, 4, 7, 8, key, &sreq, &sresp);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
uint8_t hdata[250] = {0};
int hdatalen = sizeof(hdata);
CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen);
if (hdatalen && hdatalen != 2) {
PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only");
CLIParserFree(ctx);
return PM3_EINVARG;
}
uint16_t fileId = defaultFileId;
bool useFileID = false;
if (hdatalen) {
fileId = (hdata[0] << 8) + hdata[1];
useFileID = true;
}
hdatalen = sizeof(hdata);
CLIGetHexWithReturn(ctx, 6, hdata, &hdatalen);
if (hdatalen && (hdatalen < 1 || hdatalen > 16)) {
PrintAndLogEx(ERR, _RED_("ERROR:") " application id length must be 1-16 bytes only");
CLIParserFree(ctx);
return PM3_EINVARG;
}
uint8_t aid[16] = {0};
size_t aidLen = 0;
if (hdatalen) {
memcpy(aid, hdata, hdatalen);
aidLen = hdatalen;
} else {
memcpy(aid, defaultAID, defaultAIDLength);
aidLen = defaultAIDLength;
}
bool noauth = arg_get_lit(ctx, 9);
bool needCommit = arg_get_lit(ctx, 10);
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 (useFileID)
PrintAndLogEx(INFO, "File id " _CYAN_("%x"), fileId);
else
PrintAndLogEx(INFO, "Application ID " _CYAN_("%s"), sprint_hex_inrow(aid, aidLen));
if (!noauth)
PrintAndLogEx(INFO, "key id " _YELLOW_("%d") " key " _YELLOW_("%s")
, keyId
, sprint_hex(key, CIPURSE_AES_KEY_LENGTH)
);
}
if (!noauth) {
bool bres = CIPURSEChannelAuthenticate(keyId, key, verbose);
if (bres == false) {
if (verbose)
PrintAndLogEx(ERR, "Authentication ( " _RED_("fail") " )");
DropField();
return PM3_ESOFT;
}
// set channel security levels
CIPURSECSetActChannelSecurityLevels(sreq, sresp);
}
if (needCommit) {
sw = 0;
res = CIPURSECommitTransaction(&sw);
if (res != 0 || sw != 0x9000)
PrintAndLogEx(WARNING, "Commit " _YELLOW_("ERROR") ". Card returns 0x%04x", sw);
}
DropField(); DropField();
return PM3_SUCCESS; return PM3_SUCCESS;
@ -778,8 +986,9 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf cipurse delete", 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", "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\n"
"hf cipurse delete -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and delete file\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");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -1000,6 +1209,7 @@ static command_t CommandTable[] = {
{"read", CmdHFCipurseReadFile, IfPm3Iso14443a, "Read binary file"}, {"read", CmdHFCipurseReadFile, IfPm3Iso14443a, "Read binary file"},
{"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file"}, {"write", CmdHFCipurseWriteFile, IfPm3Iso14443a, "Write binary file"},
{"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes"}, {"aread", CmdHFCipurseReadFileAttr, IfPm3Iso14443a, "Read file attributes"},
{"formatall", CmdHFCipurseFormatAll, IfPm3Iso14443a, "Erase all the data from chip"},
{"create", CmdHFCipurseCreateDGI, IfPm3Iso14443a, "Create file, application, key via DGI record"}, {"create", CmdHFCipurseCreateDGI, IfPm3Iso14443a, "Create file, application, key via DGI record"},
{"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file"}, {"delete", CmdHFCipurseDeleteFile, IfPm3Iso14443a, "Delete file"},
{"default", CmdHFCipurseDefault, IfPm3Iso14443a, "Set default key and file id for all the other commands"}, {"default", CmdHFCipurseDefault, IfPm3Iso14443a, "Set default key and file id for all the other commands"},