diff --git a/client/src/cmdhfcipurse.c b/client/src/cmdhfcipurse.c index d099d3a1c..b49642083 100644 --- a/client/src/cmdhfcipurse.c +++ b/client/src/cmdhfcipurse.c @@ -169,6 +169,157 @@ static int CmdHFCipurseInfo(const char *Cmd) { 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) { + uint8_t hdata[250] = {0}; + int hdatalen = sizeof(hdata); + if (keyid) { + if (CLIParamHexToBuf(arg_get_str(ctx, keyid), hdata, hdatalen, &hdatalen)) + return PM3_ESOFT; + + if (hdatalen && hdatalen != 16) { + PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); + return PM3_EINVARG; + } + if (hdatalen) + memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); + else + memcpy(key, defaultKey, sizeof(defaultKey)); + } + + if (useaid) + *useaid = false; + if (aidid && aid && aidlen) { + hdatalen = sizeof(hdata); + CLIGetHexWithReturn(ctx, aidid, hdata, &hdatalen); + if (hdatalen && (hdatalen < 1 || hdatalen > 16)) { + PrintAndLogEx(ERR, _RED_("ERROR:") " application id length must be 1-16 bytes only"); + return PM3_EINVARG; + } + + *aidlen = 0; + if (hdatalen) { + memcpy(aid, hdata, hdatalen); + *aidlen = hdatalen; + if (useaid) + *useaid = true; + } else { + memcpy(aid, defaultAID, defaultAIDLength); + *aidlen = defaultAIDLength; + } + } + + if (usefid) + *usefid = false; + if (fidid && fid) { + hdatalen = sizeof(hdata); + CLIGetHexWithReturn(ctx, fidid, hdata, &hdatalen); + if (hdatalen && hdatalen != 2) { + PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); + return PM3_EINVARG; + } + + *fid = defaultFileId; + if (hdatalen) { + *fid = (hdata[0] << 8) + hdata[1]; + if (usefid) + *usefid = true; + } + } + + if (sreqid && srespid && sreq && sresp) { + *sreq = CPSMACed; + *sresp = CPSMACed; + + char cdata[250] = {0}; + int cdatalen = sizeof(cdata); + cdatalen--; // for trailer 0x00 + if (CLIParamStrToBuf(arg_get_str(ctx, sreqid), (uint8_t *)cdata, cdatalen, &cdatalen)) + return PM3_ESOFT; + + if (cdatalen) { + str_lower(cdata); + if (strcmp(cdata, "plain") == 0) + *sreq = CPSPlain; + else if (strcmp(cdata, "mac") == 0) + *sreq = CPSMACed; + else if (strcmp(cdata, "enc") == 0 || strcmp(cdata, "encode") == 0 || strcmp(cdata, "encrypted") == 0) + *sreq = CPSEncrypted; + else { + PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain | mac | encode"); + return PM3_EINVARG; + } + } + + cdatalen = sizeof(cdata); + memset(cdata, 0, cdatalen); + cdatalen--; // for trailer 0x00 + if (CLIParamStrToBuf(arg_get_str(ctx, srespid), (uint8_t *)cdata, cdatalen, &cdatalen)) + return PM3_ESOFT; + + if (cdatalen) { + str_lower(cdata); + if (strcmp(cdata, "plain") == 0) + *sresp = CPSPlain; + else if (strcmp(cdata, "mac") == 0) + *sresp = CPSMACed; + else if (strcmp(cdata, "enc") == 0 || strcmp(cdata, "encode") == 0 || strcmp(cdata, "encrypted") == 0) + *sresp = CPSEncrypted; + else { + PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain | mac | encode"); + return PM3_EINVARG; + } + } + } + + 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) { + int res = 0; + if (useAID && aidLen > 0) { + res = CIPURSESelectAID(true, true, aid, aidLen, buf, bufSize, len, sw); + if (res != 0 || *sw != 0x9000) { + if (verbose) + PrintAndLogEx(ERR, "Cipurse select application " _GREEN_("%s ") _RED_("error") ". Card returns 0x%04x", sprint_hex_inrow(aid, aidLen), *sw); + return PM3_ESOFT; + } + if (verbose) + PrintAndLogEx(INFO, "Cipurse select application " _CYAN_("%s ") _GREEN_("OK"), sprint_hex_inrow(aid, aidLen)); + } else if (useFID) { + res = CIPURSESelectFileEx(true, true, fileId, buf, bufSize, len, sw); + if (res != 0 || *sw != 0x9000) { + if (verbose) + PrintAndLogEx(ERR, "Cipurse select file 0x%04x " _RED_("error") ". Card returns 0x%04x", fileId, *sw); + return PM3_ESOFT; + } + if (verbose) + PrintAndLogEx(INFO, "Cipurse select file " _CYAN_("0x%04x ") _GREEN_("OK"), fileId); + } else if (selectDefaultFile) { + res = CIPURSESelectMFDefaultFileEx(true, true, buf, bufSize, len, sw); + if (res != 0 || *sw != 0x9000) { + if (verbose) + PrintAndLogEx(ERR, "Cipurse select default file " _RED_("error") ". Card returns 0x%04x", *sw); + return PM3_ESOFT; + } + if (verbose) + PrintAndLogEx(INFO, "Cipurse select default file " _GREEN_("OK")); + } else { + res = CIPURSESelect(true, true, buf, bufSize, len, sw); + if (res != 0 || *sw != 0x9000) { + if (verbose) + PrintAndLogEx(ERR, "Cipurse select default application " _RED_("error") ". Card returns 0x%04x", *sw); + return PM3_ESOFT; + } + if (verbose) + PrintAndLogEx(INFO, "Cipurse select default application " _GREEN_("OK")); + } + + return PM3_SUCCESS; +} + + static int CmdHFCipurseSelect(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse select", @@ -183,7 +334,7 @@ static int CmdHFCipurseSelect(const char *Cmd) { arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), arg_lit0("t", "tlv", "TLV decode returned data"), - arg_str0("k", "aid", "", "application ID (AID)"), + arg_str0(NULL, "aid", "", "application ID (AID)"), arg_str0(NULL, "fid", "", "file ID (FID)"), arg_lit0(NULL, "mfd", "select masterfile by empty id"), arg_param_end @@ -194,80 +345,30 @@ static int CmdHFCipurseSelect(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); bool showTLV = arg_get_lit(ctx, 3); - uint8_t hdata[250] = {0}; - int hdatalen = sizeof(hdata); - CLIGetHexWithReturn(ctx, 4, 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; - } - - hdatalen = sizeof(hdata); - CLIGetHexWithReturn(ctx, 5, hdata, &hdatalen); - if (hdatalen && hdatalen != 2) { - PrintAndLogEx(ERR, _RED_("ERROR:") " file id length must be 2 bytes only"); + bool useAID = false; + uint16_t fileId = defaultFileId; + bool useFID = false; + int res = CLIParseCommandParameters(ctx, 0, 4, 5, 0, 0, NULL, aid, &aidLen, &useAID, &fileId, &useFID, NULL, NULL); + if (res || (useAID && useFID)) { CLIParserFree(ctx); return PM3_EINVARG; } - uint16_t fileId = 0; - bool useFileID = false; - if (hdatalen) { - fileId = (hdata[0] << 8) + hdata[1]; - useFileID = true; - } - bool selmfd = arg_get_lit(ctx, 6); - SetAPDULogging(APDULogging); - CLIParserFree(ctx); + SetAPDULogging(APDULogging); + uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = 0; - - if (aidLen > 0) { - res = CIPURSESelectAID(true, false, aid, aidLen, buf, sizeof(buf), &len, &sw); - if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select application " _GREEN_("%s ") _RED_("error") ". Card returns 0x%04x", sprint_hex_inrow(aid, aidLen), sw); - DropField(); - return PM3_ESOFT; - } - PrintAndLogEx(INFO, "Cipurse select application " _CYAN_("%s ") _GREEN_("OK"), sprint_hex_inrow(aid, aidLen)); - } else if (useFileID) { - res = CIPURSESelectFileEx(true, false, fileId, buf, sizeof(buf), &len, &sw); - if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select file 0x%04x " _RED_("error") ". Card returns 0x%04x", fileId, sw); - DropField(); - return PM3_ESOFT; - } - PrintAndLogEx(INFO, "Cipurse select file " _CYAN_("0x%04x ") _GREEN_("OK"), fileId); - } else if (selmfd) { - res = CIPURSESelectMFDefaultFileEx(true, false, buf, sizeof(buf), &len, &sw); - if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select default file " _RED_("error") ". Card returns 0x%04x", sw); - DropField(); - return PM3_ESOFT; - } - PrintAndLogEx(INFO, "Cipurse select default file " _GREEN_("OK")); - } else { - res = CIPURSESelect(true, false, buf, sizeof(buf), &len, &sw); - if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select default application " _RED_("error") ". Card returns 0x%04x", sw); - DropField(); - return PM3_ESOFT; - } - PrintAndLogEx(INFO, "Cipurse select default application " _GREEN_("OK")); + res = SelectCommand(selmfd, useAID, aid, aidLen, useFID, fileId, true, buf, sizeof(buf), &len, &sw); + if (res != 0 || sw != 0x9000) { + DropField(); + return PM3_ESOFT; } if (len > 0) { @@ -280,6 +381,7 @@ static int CmdHFCipurseSelect(const char *Cmd) { TLVPrintFromBuffer(buf, len); } + DropField(); return PM3_SUCCESS; } @@ -294,6 +396,9 @@ static int CmdHFCipurseAuth(const char *Cmd) { arg_param_begin, arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("v", "verbose", "show technical data"), + arg_str0(NULL, "aid", "", "application ID (AID)"), + arg_str0(NULL, "fid", "", "file ID (FID)"), + arg_lit0(NULL, "mfd", "select masterfile by empty id"), arg_int0("n", NULL, "", "key ID"), arg_str0("k", "key", "", "Auth key"), arg_param_end @@ -302,34 +407,32 @@ static int CmdHFCipurseAuth(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - uint8_t keyId = arg_get_int_def(ctx, 3, defaultKeyId); - uint8_t hdata[250] = {0}; - int hdatalen = sizeof(hdata); - CLIGetHexWithReturn(ctx, 4, hdata, &hdatalen); - if (hdatalen && hdatalen != 16) { - PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); + 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, 7, 3, 4, 0, 0, key, aid, &aidLen, &useAID, &fileId, &useFID, NULL, NULL); + if (res || (useAID && useFID)) { CLIParserFree(ctx); return PM3_EINVARG; } - uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; - if (hdatalen) - memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); - else - memcpy(key, defaultKey, sizeof(defaultKey)); - - SetAPDULogging(APDULogging); + bool selmfd = arg_get_lit(ctx, 5); + uint8_t keyId = arg_get_int_def(ctx, 6, defaultKeyId); CLIParserFree(ctx); + SetAPDULogging(APDULogging); + size_t len = 0; uint16_t sw = 0; uint8_t buf[APDU_RES_LEN] = {0}; - int res = CIPURSESelect(true, true, buf, sizeof(buf), &len, &sw); + res = SelectCommand(selmfd, useAID, aid, aidLen, useFID, fileId, true, buf, sizeof(buf), &len, &sw); if (res != 0 || sw != 0x9000) { - PrintAndLogEx(ERR, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw); DropField(); return PM3_ESOFT; } @@ -357,67 +460,6 @@ static int CmdHFCipurseAuth(const char *Cmd) { return (bres) ? PM3_SUCCESS : PM3_ESOFT; } -static int CLIParseKeyAndSecurityLevels(CLIParserContext *ctx, size_t keyid, size_t sreqid, size_t srespid, uint8_t *key, CipurseChannelSecurityLevel *sreq, CipurseChannelSecurityLevel *sresp) { - uint8_t hdata[250] = {0}; - int hdatalen = sizeof(hdata); - if (CLIParamHexToBuf(arg_get_str(ctx, keyid), hdata, hdatalen, &hdatalen)) - return PM3_ESOFT; - - if (hdatalen && hdatalen != 16) { - PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); - return PM3_EINVARG; - } - if (hdatalen) - memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); - else - memcpy(key, defaultKey, sizeof(defaultKey)); - - *sreq = CPSMACed; - *sresp = CPSMACed; - - char cdata[250] = {0}; - int cdatalen = sizeof(cdata); - cdatalen--; // for trailer 0x00 - if (CLIParamStrToBuf(arg_get_str(ctx, sreqid), (uint8_t *)cdata, cdatalen, &cdatalen)) - return PM3_ESOFT; - - if (cdatalen) { - str_lower(cdata); - if (strcmp(cdata, "plain") == 0) - *sreq = CPSPlain; - else if (strcmp(cdata, "mac") == 0) - *sreq = CPSMACed; - else if (strcmp(cdata, "enc") == 0 || strcmp(cdata, "encode") == 0 || strcmp(cdata, "encrypted") == 0) - *sreq = CPSEncrypted; - else { - PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain | mac | encode"); - return PM3_EINVARG; - } - } - - cdatalen = sizeof(cdata); - memset(cdata, 0, cdatalen); - cdatalen--; // for trailer 0x00 - if (CLIParamStrToBuf(arg_get_str(ctx, srespid), (uint8_t *)cdata, cdatalen, &cdatalen)) - return PM3_ESOFT; - - if (cdatalen) { - str_lower(cdata); - if (strcmp(cdata, "plain") == 0) - *sresp = CPSPlain; - else if (strcmp(cdata, "mac") == 0) - *sresp = CPSMACed; - else if (strcmp(cdata, "enc") == 0 || strcmp(cdata, "encode") == 0 || strcmp(cdata, "encrypted") == 0) - *sresp = CPSEncrypted; - else { - PrintAndLogEx(ERR, _RED_("ERROR:") " security level can be only: plain | mac | encode"); - return PM3_EINVARG; - } - } - - return PM3_SUCCESS; -} - static int CmdHFCipurseReadFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cipurse read", @@ -448,24 +490,14 @@ static int CmdHFCipurseReadFile(const char *Cmd) { CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; - int res = CLIParseKeyAndSecurityLevels(ctx, 4, 8, 9, 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; - if (hdatalen) - fileId = (hdata[0] << 8) + hdata[1]; + bool useFID = false; + int res = CLIParseCommandParameters(ctx, 4, 0, 5, 8, 9, key, NULL, NULL, NULL, &fileId, &useFID, &sreq, &sresp); + if (res || useFID == false) { + CLIParserFree(ctx); + return PM3_EINVARG; + } size_t offset = arg_get_int_def(ctx, 6, 0); @@ -561,30 +593,21 @@ static int CmdHFCipurseWriteFile(const char *Cmd) { CipurseChannelSecurityLevel sresp = CPSMACed; uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; - int res = CLIParseKeyAndSecurityLevels(ctx, 4, 8, 9, key, &sreq, &sresp); - if (res) { - CLIParserFree(ctx); - return PM3_EINVARG; - } uint16_t fileId = defaultFileId; - - 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"); + bool useFID = false; + int res = CLIParseCommandParameters(ctx, 4, 0, 5, 8, 9, key, NULL, NULL, NULL, &fileId, &useFID, &sreq, &sresp); + if (res || useFID == false) { CLIParserFree(ctx); return PM3_EINVARG; } - if (hdatalen) - fileId = (hdata[0] << 8) + hdata[1]; size_t offset = arg_get_int_def(ctx, 6, 0); bool noAuth = arg_get_lit(ctx, 7); - hdatalen = sizeof(hdata); + uint8_t hdata[250] = {0}; + int hdatalen = sizeof(hdata); CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen); if (hdatalen == 0) { PrintAndLogEx(ERR, _RED_("ERROR:") " file content length must be more 0"); @@ -685,24 +708,14 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) { 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; - if (hdatalen) - fileId = (hdata[0] << 8) + hdata[1]; + bool useFID = false; + int res = CLIParseCommandParameters(ctx, 4, 0, 5, 7, 8, key, NULL, NULL, NULL, &fileId, &useFID, &sreq, &sresp); + if (res || useFID == false) { + CLIParserFree(ctx); + return PM3_EINVARG; + } bool noAuth = arg_get_lit(ctx, 6); bool seladf = arg_get_lit(ctx, 9); @@ -812,7 +825,7 @@ static int CmdHFCipurseFormatAll(const char *Cmd) { CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; - int res = CLIParseKeyAndSecurityLevels(ctx, 4, 5, 6, key, &sreq, &sresp); + int res = CLIParseCommandParameters(ctx, 4, 0, 0, 5, 6, key, NULL, NULL, NULL, NULL, NULL, &sreq, &sresp); if (res) { CLIParserFree(ctx); return PM3_EINVARG; @@ -898,7 +911,10 @@ static int CmdHFCipurseCreateDGI(const char *Cmd) { CipurseChannelSecurityLevel sreq = CPSMACed; CipurseChannelSecurityLevel sresp = CPSMACed; uint8_t key[CIPURSE_AES_KEY_LENGTH] = {0}; - int res = CLIParseKeyAndSecurityLevels(ctx, 4, 6, 7, key, &sreq, &sresp); + + uint16_t fileId = defaultFileId; + bool useFID = false; + int res = CLIParseCommandParameters(ctx, 4, 0, 0, 6, 7, key, NULL, NULL, NULL, &fileId, &useFID, &sreq, &sresp); if (res) { CLIParserFree(ctx); return PM3_EINVARG; @@ -993,7 +1009,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { arg_lit0(NULL, "commit", "commit "), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIExecWithReturn(ctx, Cmd, argtable, false); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); @@ -1002,44 +1018,17 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { 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 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); + // useAID and useFID in the same state + if (res || !(useAID ^ useFID)) { + CLIParserFree(ctx); + return PM3_EINVARG; } bool noauth = arg_get_lit(ctx, 9); @@ -1060,7 +1049,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { } if (verbose) { - if (useFileID) + if (useFID) PrintAndLogEx(INFO, "File id " _CYAN_("%x"), fileId); else PrintAndLogEx(INFO, "Application ID " _CYAN_("%s"), sprint_hex_inrow(aid, aidLen)); @@ -1085,7 +1074,7 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) { CIPURSECSetActChannelSecurityLevels(sreq, sresp); } - if (useFileID) { + 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, diff --git a/doc/cipurse.md b/doc/cipurse.md index d158752fe..a419844b7 100644 --- a/doc/cipurse.md +++ b/doc/cipurse.md @@ -57,6 +57,27 @@ Each file can only have an access control list that specifies what operation the ## How to +### How to select application or file +^[Top](#top) + +1. select PTSE +```hf cipurse select --aid a0000005070100``` + +select it with display output in raw and tlv views options +```hf cipurse select --aid a0000005070100 -vt``` + +2. select application by Application ID (AID) +```hf cipurse select --aid 4144204631``` + +3. select application/file by file ID (FID) +```hf cipurse select --fid 2000``` + +4. select master file by file ID (FID) +```hf cipurse select --fid 3F00``` + +5. select default file (usually it master file) +```hf cipurse select --mfd``` + ### How to personalize card ^[Top](#top)