1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2021 Merlok
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // High frequency FIDO U2F and FIDO2 contactless authenticators
9 //-----------------------------------------------------------------------------
11 // JAVA implementation here:
13 // https://github.com/duychuongvn/cipurse-card-core
14 //-----------------------------------------------------------------------------
16 #include "cmdhffido.h"
18 #include "cmdparser.h" // command_t
19 #include "commonutil.h"
21 #include "proxmark3.h"
22 #include "emv/emvcore.h"
23 #include "emv/emvjson.h"
24 #include "cliparser.h"
25 #include "cmdhfcipurse.h"
26 #include "cipurse/cipursecore.h"
27 #include "cipurse/cipursecrypto.h"
32 #include "fileutils.h" // laodFileJSONroot
34 static int CmdHelp(const char *Cmd
);
36 static int CmdHFCipurseInfo(const char *Cmd
) {
37 CLIParserContext
*ctx
;
38 CLIParserInit(&ctx
, "hf cipurse info",
39 "Get info from cipurse tags",
46 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
49 // info about 14a part
50 infoHF14A(false, false, false);
53 PrintAndLogEx(INFO
, "-----------" _CYAN_("CIPURSE Info") "---------------------------------");
54 SetAPDULogging(false);
56 uint8_t buf
[APDU_RES_LEN
] = {0};
59 int res
= CIPURSESelect(true, true, buf
, sizeof(buf
), &len
, &sw
);
68 PrintAndLogEx(INFO
, "Not a CIPURSE card. APDU response: %04x - %s", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
70 PrintAndLogEx(ERR
, "APDU exchange error. Card returns 0x0000");
76 PrintAndLogEx(INFO
, "Cipurse card ( " _GREEN_("ok") " )");
78 res
= CIPURSESelectFile(0x2ff7, buf
, sizeof(buf
), &len
, &sw
);
79 if (res
!= 0 || sw
!= 0x9000) {
84 res
= CIPURSEReadBinary(0, buf
, sizeof(buf
), &len
, &sw
);
85 if (res
!= 0 || sw
!= 0x9000) {
91 PrintAndLogEx(INFO
, "Info file ( " _GREEN_("ok") " )");
92 PrintAndLogEx(INFO
, "[%zu]: %s", len
, sprint_hex(buf
, len
));
93 CIPURSEPrintInfoFile(buf
, len
);
100 static int CmdHFCipurseAuth(const char *Cmd
) {
101 CLIParserContext
*ctx
;
102 CLIParserInit(&ctx
, "hf cipurse auth",
103 "Authenticate with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
104 "hf cipurse auth -> Authenticate with keyID 1, default key\n"
105 "hf cipurse auth -n 2 -k 65656565656565656565656565656565 -> Authenticate keyID 2 with key\n");
109 arg_lit0("a", "apdu", "show APDU requests and responses"),
110 arg_lit0("v", "verbose", "show technical data"),
111 arg_int0("n", NULL
, "<dec>", "key ID"),
112 arg_str0("k", "key", "<hex>", "Auth key"),
115 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
117 bool APDULogging
= arg_get_lit(ctx
, 1);
118 bool verbose
= arg_get_lit(ctx
, 2);
119 uint8_t keyId
= arg_get_int_def(ctx
, 3, 1);
121 uint8_t hdata
[250] = {0};
122 int hdatalen
= sizeof(hdata
);
123 CLIGetHexWithReturn(ctx
, 4, hdata
, &hdatalen
);
124 if (hdatalen
&& hdatalen
!= 16) {
125 PrintAndLogEx(ERR
, _RED_("ERROR:") " key length for AES128 must be 16 bytes only");
130 uint8_t key
[] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73};
132 memcpy(key
, hdata
, CIPURSE_AES_KEY_LENGTH
);
134 SetAPDULogging(APDULogging
);
140 uint8_t buf
[APDU_RES_LEN
] = {0};
142 int res
= CIPURSESelect(true, true, buf
, sizeof(buf
), &len
, &sw
);
143 if (res
!= 0 || sw
!= 0x9000) {
144 PrintAndLogEx(ERR
, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw
);
149 uint8_t kvv
[CIPURSE_KVV_LENGTH
] = {0};
150 CipurseCGetKVV(key
, kvv
);
152 PrintAndLogEx(INFO
, "Key id" _YELLOW_("%d") " key " _YELLOW_("%s") " KVV " _YELLOW_("%s")
154 , sprint_hex(key
, CIPURSE_AES_KEY_LENGTH
)
155 , sprint_hex_inrow(kvv
, CIPURSE_KVV_LENGTH
)
159 bool bres
= CIPURSEChannelAuthenticate(keyId
, key
, verbose
);
161 if (verbose
== false) {
163 PrintAndLogEx(INFO
, "Authentication ( " _GREEN_("ok") " )");
165 PrintAndLogEx(ERR
, "Authentication ( " _RED_("fail") " )");
169 return (bres
) ? PM3_SUCCESS
: PM3_ESOFT
;
172 static int CLIParseKeyAndSecurityLevels(CLIParserContext
*ctx
, size_t keyid
, size_t sreqid
, size_t srespid
, uint8_t *key
, CipurseChannelSecurityLevel
*sreq
, CipurseChannelSecurityLevel
*sresp
) {
173 uint8_t hdata
[250] = {0};
174 int hdatalen
= sizeof(hdata
);
175 CLIGetHexWithReturn(ctx
, keyid
, hdata
, &hdatalen
);
176 if (hdatalen
&& hdatalen
!= 16) {
177 PrintAndLogEx(ERR
, _RED_("ERROR:") " key length for AES128 must be 16 bytes only");
181 memcpy(key
, hdata
, CIPURSE_AES_KEY_LENGTH
);
186 char cdata
[250] = {0};
187 int cdatalen
= sizeof(cdata
);
188 cdatalen
--; // for trailer 0x00
189 CLIGetStrWithReturn(ctx
, sreqid
, (uint8_t *)cdata
, &cdatalen
);
192 if (strcmp(cdata
, "plain") == 0)
194 else if (strcmp(cdata
, "mac") == 0)
196 else if (strcmp(cdata
, "enc") == 0 || strcmp(cdata
, "encode") == 0 || strcmp(cdata
, "encrypted") == 0)
197 *sreq
= CPSEncrypted
;
199 PrintAndLogEx(ERR
, _RED_("ERROR:") " security level can be only: plain | mac | encode");
204 cdatalen
= sizeof(cdata
);
205 memset(cdata
, 0, cdatalen
);
206 cdatalen
--; // for trailer 0x00
207 CLIGetStrWithReturn(ctx
, srespid
, (uint8_t *)cdata
, &cdatalen
);
210 if (strcmp(cdata
, "plain") == 0)
212 else if (strcmp(cdata
, "mac") == 0)
214 else if (strcmp(cdata
, "enc") == 0 || strcmp(cdata
, "encode") == 0 || strcmp(cdata
, "encrypted") == 0)
215 *sresp
= CPSEncrypted
;
217 PrintAndLogEx(ERR
, _RED_("ERROR:") " security level can be only: plain | mac | encode");
225 static int CmdHFCipurseReadFile(const char *Cmd
) {
226 CLIParserContext
*ctx
;
227 CLIParserInit(&ctx
, "hf cipurse read",
228 "Read file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
229 "hf cipurse read -f 2ff7 -> Authenticate with keyID 1, read file with id 2ff7\n"
230 "hf cipurse read -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and read file\n");
234 arg_lit0("a", "apdu", "show APDU requests and responses"),
235 arg_lit0("v", "verbose", "show technical data"),
236 arg_int0("n", NULL
, "<dec>", "key ID"),
237 arg_str0("k", "key", "<hex>", "Auth key"),
238 arg_str0(NULL
, "fid", "<hex>", "file ID"),
239 arg_int0("o", "offset", "<dec>", "offset for reading data from file"),
240 arg_lit0(NULL
, "noauth", "read file without authentication"),
241 arg_str0(NULL
, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"),
242 arg_str0(NULL
, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"),
245 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
248 bool APDULogging
= arg_get_lit(ctx
, 1);
249 bool verbose
= arg_get_lit(ctx
, 2);
250 uint8_t keyId
= arg_get_int_def(ctx
, 3, 1);
252 CipurseChannelSecurityLevel sreq
= CPSMACed
;
253 CipurseChannelSecurityLevel sresp
= CPSMACed
;
254 uint8_t key
[] = CIPURSE_DEFAULT_KEY
;
255 int res
= CLIParseKeyAndSecurityLevels(ctx
, 4, 8, 9, key
, &sreq
, &sresp
);
261 uint8_t hdata
[250] = {0};
262 int hdatalen
= sizeof(hdata
);
263 CLIGetHexWithReturn(ctx
, 5, hdata
, &hdatalen
);
264 if (hdatalen
&& hdatalen
!= 2) {
265 PrintAndLogEx(ERR
, _RED_("ERROR:") " file id length must be 2 bytes only");
270 uint16_t fileId
= 0x2ff7;
272 fileId
= (hdata
[0] << 8) + hdata
[1];
274 size_t offset
= arg_get_int_def(ctx
, 6, 0);
276 bool noAuth
= arg_get_lit(ctx
, 7);
278 SetAPDULogging(APDULogging
);
284 uint8_t buf
[APDU_RES_LEN
] = {0};
286 res
= CIPURSESelect(true, true, buf
, sizeof(buf
), &len
, &sw
);
287 if (res
!= 0 || sw
!= 0x9000) {
288 PrintAndLogEx(ERR
, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw
);
294 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s"), fileId
, offset
, keyId
, sprint_hex(key
, CIPURSE_AES_KEY_LENGTH
));
296 if (noAuth
== false) {
297 bool bres
= CIPURSEChannelAuthenticate(keyId
, key
, verbose
);
299 if (verbose
== false)
300 PrintAndLogEx(ERR
, "Authentication ( " _RED_("fail") " )");
305 // set channel security levels
306 CIPURSECSetActChannelSecurityLevels(sreq
, sresp
);
309 res
= CIPURSESelectFile(fileId
, buf
, sizeof(buf
), &len
, &sw
);
310 if (res
!= 0 || sw
!= 0x9000) {
311 if (verbose
== false)
312 PrintAndLogEx(ERR
, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw
);
318 PrintAndLogEx(INFO
, "Select file 0x%x ( " _GREEN_("ok") " )", fileId
);
320 res
= CIPURSEReadBinary(offset
, buf
, sizeof(buf
), &len
, &sw
);
321 if (res
!= 0 || sw
!= 0x9000) {
322 if (verbose
== false)
323 PrintAndLogEx(ERR
, "File read " _RED_("ERROR") ". Card returns 0x%04x", sw
);
329 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " is empty", fileId
);
331 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " data[%zu]: %s", fileId
, len
, sprint_hex(buf
, len
));
337 static int CmdHFCipurseWriteFile(const char *Cmd
) {
338 CLIParserContext
*ctx
;
339 CLIParserInit(&ctx
, "hf cipurse write",
340 "Write file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
341 "hf cipurse write -f 2ff7 -> Authenticate with keyID 1, write file with id 2ff7\n"
342 "hf cipurse write -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and write file\n");
346 arg_lit0("a", "apdu", "show APDU requests and responses"),
347 arg_lit0("v", "verbose", "show technical data"),
348 arg_int0("n", NULL
, "<dec>", "key ID"),
349 arg_str0("k", "key", "<hex>", "Auth key"),
350 arg_str0(NULL
, "fid", "<hex>", "file ID"),
351 arg_int0("o", "offset", "<dec>", "offset for reading data from file"),
352 arg_lit0(NULL
, "noauth", "read file without authentication"),
353 arg_str0(NULL
, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"),
354 arg_str0(NULL
, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"),
355 arg_str0("d", "data", "<hex>", "hex data to write to new file"),
358 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
360 bool APDULogging
= arg_get_lit(ctx
, 1);
361 bool verbose
= arg_get_lit(ctx
, 2);
362 uint8_t keyId
= arg_get_int_def(ctx
, 3, 1);
364 CipurseChannelSecurityLevel sreq
= CPSMACed
;
365 CipurseChannelSecurityLevel sresp
= CPSMACed
;
367 uint8_t key
[] = CIPURSE_DEFAULT_KEY
;
368 int res
= CLIParseKeyAndSecurityLevels(ctx
, 4, 8, 9, key
, &sreq
, &sresp
);
374 uint16_t fileId
= 0x2ff7;
376 uint8_t hdata
[250] = {0};
377 int hdatalen
= sizeof(hdata
);
378 CLIGetHexWithReturn(ctx
, 5, hdata
, &hdatalen
);
379 if (hdatalen
&& hdatalen
!= 2) {
380 PrintAndLogEx(ERR
, _RED_("ERROR:") " file id length must be 2 bytes only");
385 fileId
= (hdata
[0] << 8) + hdata
[1];
387 size_t offset
= arg_get_int_def(ctx
, 6, 0);
389 bool noAuth
= arg_get_lit(ctx
, 7);
391 hdatalen
= sizeof(hdata
);
392 CLIGetHexWithReturn(ctx
, 10, hdata
, &hdatalen
);
394 PrintAndLogEx(ERR
, _RED_("ERROR:") " file content length must be more 0");
399 SetAPDULogging(APDULogging
);
405 uint8_t buf
[APDU_RES_LEN
] = {0};
407 res
= CIPURSESelect(true, true, buf
, sizeof(buf
), &len
, &sw
);
408 if (res
!= 0 || sw
!= 0x9000) {
409 PrintAndLogEx(ERR
, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw
);
415 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " offset " _YELLOW_("%zu") " key id " _YELLOW_("%d") " key " _YELLOW_("%s")
419 , sprint_hex(key
, CIPURSE_AES_KEY_LENGTH
)
421 PrintAndLogEx(INFO
, "data[%d]: %s", hdatalen
, sprint_hex(hdata
, hdatalen
));
424 if (noAuth
== false) {
425 bool bres
= CIPURSEChannelAuthenticate(keyId
, key
, verbose
);
427 if (verbose
== false)
428 PrintAndLogEx(ERR
, "Authentication ( " _RED_("fail") " )");
433 // set channel security levels
434 CIPURSECSetActChannelSecurityLevels(sreq
, sresp
);
437 res
= CIPURSESelectFile(fileId
, buf
, sizeof(buf
), &len
, &sw
);
438 if (res
!= 0 || sw
!= 0x9000) {
439 if (verbose
== false)
440 PrintAndLogEx(ERR
, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw
);
446 PrintAndLogEx(INFO
, "Select file 0x%x ( " _GREEN_("ok") " )", fileId
);
448 res
= CIPURSEUpdateBinary(offset
, hdata
, hdatalen
, buf
, sizeof(buf
), &len
, &sw
);
449 if (res
!= 0 || sw
!= 0x9000) {
450 if (verbose
== false)
451 PrintAndLogEx(ERR
, "File write " _RED_("ERROR") ". Card returns 0x%04x", sw
);
456 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " successfully written", fileId
);
462 static int CmdHFCipurseReadFileAttr(const char *Cmd
) {
463 CLIParserContext
*ctx
;
464 CLIParserInit(&ctx
, "hf cipurse aread",
465 "Read file attributes by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
466 "hf cipurse aread -f 2ff7 -> Authenticate with keyID 1, read file attributes with id 2ff7\n"
467 "hf cipurse aread -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2, read file attributes\n");
471 arg_lit0("a", "apdu", "show APDU requests and responses"),
472 arg_lit0("v", "verbose", "show technical data"),
473 arg_int0("n", NULL
, "<dec>", "key ID"),
474 arg_str0("k", "key", "<hex>", "Auth key"),
475 arg_str0(NULL
, "fid", "<hex>", "file ID"),
476 arg_lit0(NULL
, "noauth", "read file attributes without authentication"),
477 arg_str0(NULL
, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"),
478 arg_str0(NULL
, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"),
479 arg_lit0(NULL
, "sel-adf", "show info about ADF itself"),
480 arg_lit0(NULL
, "sel-mf", "show info about master file"),
483 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
485 bool APDULogging
= arg_get_lit(ctx
, 1);
486 bool verbose
= arg_get_lit(ctx
, 2);
487 uint8_t keyId
= arg_get_int_def(ctx
, 3, 1);
489 CipurseChannelSecurityLevel sreq
= CPSMACed
;
490 CipurseChannelSecurityLevel sresp
= CPSMACed
;
491 uint8_t key
[] = CIPURSE_DEFAULT_KEY
;
492 int res
= CLIParseKeyAndSecurityLevels(ctx
, 4, 7, 8, key
, &sreq
, &sresp
);
498 uint8_t hdata
[250] = {0};
499 int hdatalen
= sizeof(hdata
);
500 CLIGetHexWithReturn(ctx
, 5, hdata
, &hdatalen
);
501 if (hdatalen
&& hdatalen
!= 2) {
502 PrintAndLogEx(ERR
, _RED_("ERROR:") " file id length must be 2 bytes only");
507 uint16_t fileId
= 0x2ff7;
509 fileId
= (hdata
[0] << 8) + hdata
[1];
511 bool noAuth
= arg_get_lit(ctx
, 6);
512 bool seladf
= arg_get_lit(ctx
, 9);
513 bool selmf
= arg_get_lit(ctx
, 10);
515 SetAPDULogging(APDULogging
);
519 uint8_t buf
[APDU_RES_LEN
] = {0};
523 res
= CIPURSESelect(true, true, buf
, sizeof(buf
), &len
, &sw
);
524 if (res
!= 0 || sw
!= 0x9000) {
525 PrintAndLogEx(ERR
, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw
);
531 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " key id " _YELLOW_("%d") " key " _YELLOW_("%s")
534 , sprint_hex(key
, CIPURSE_AES_KEY_LENGTH
)
538 if (noAuth
== false) {
539 bool bres
= CIPURSEChannelAuthenticate(keyId
, key
, verbose
);
541 if (verbose
== false)
542 PrintAndLogEx(ERR
, "Authentication ( " _RED_("fail") " )");
547 // set channel security levels
548 CIPURSECSetActChannelSecurityLevels(sreq
, sresp
);
551 if (seladf
== false) {
553 res
= CIPURSESelectMFFile(buf
, sizeof(buf
), &len
, &sw
);
555 res
= CIPURSESelectFile(fileId
, buf
, sizeof(buf
), &len
, &sw
);
557 if (res
!= 0 || sw
!= 0x9000) {
558 if (verbose
== false)
559 PrintAndLogEx(ERR
, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw
);
566 PrintAndLogEx(INFO
, "Select file 0x%x ( " _GREEN_("ok") " )", fileId
);
568 res
= CIPURSEReadFileAttributes(buf
, sizeof(buf
), &len
, &sw
);
569 if (res
!= 0 || sw
!= 0x9000) {
570 if (verbose
== false)
571 PrintAndLogEx(ERR
, "File read " _RED_("ERROR") ". Card returns 0x%04x", sw
);
577 PrintAndLogEx(WARNING
, "File id " _YELLOW_("%x") " attributes is empty", fileId
);
583 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " attributes[%zu]: %s", fileId
, len
, sprint_hex(buf
, len
));
585 CIPURSEPrintFileAttr(buf
, len
);
591 static int CmdHFCipurseDeleteFile(const char *Cmd
) {
592 CLIParserContext
*ctx
;
593 CLIParserInit(&ctx
, "hf cipurse delete",
594 "Read file by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
595 "hf cipurse delete -f 2ff7 -> Authenticate with keyID 1, delete file with id 2ff7\n"
596 "hf cipurse delete -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and delete file\n");
600 arg_lit0("a", "apdu", "show APDU requests and responses"),
601 arg_lit0("v", "verbose", "show technical data"),
602 arg_int0("n", NULL
, "<dec>", "key ID"),
603 arg_str0("k", "key", "<hex>", "Auth key"),
604 arg_str0(NULL
, "fid", "<hex>", "file ID"),
605 arg_str0(NULL
, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"),
606 arg_str0(NULL
, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"),
609 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
611 bool APDULogging
= arg_get_lit(ctx
, 1);
612 bool verbose
= arg_get_lit(ctx
, 2);
613 uint8_t keyId
= arg_get_int_def(ctx
, 3, 1);
615 CipurseChannelSecurityLevel sreq
= CPSMACed
;
616 CipurseChannelSecurityLevel sresp
= CPSMACed
;
617 uint8_t key
[] = CIPURSE_DEFAULT_KEY
;
618 int res
= CLIParseKeyAndSecurityLevels(ctx
, 4, 6, 7, key
, &sreq
, &sresp
);
624 uint8_t hdata
[250] = {0};
625 int hdatalen
= sizeof(hdata
);
626 CLIGetHexWithReturn(ctx
, 5, hdata
, &hdatalen
);
627 if (hdatalen
&& hdatalen
!= 2) {
628 PrintAndLogEx(ERR
, _RED_("ERROR:") " file id length must be 2 bytes only");
633 uint16_t fileId
= 0x2ff7;
635 fileId
= (hdata
[0] << 8) + hdata
[1];
637 SetAPDULogging(APDULogging
);
641 uint8_t buf
[APDU_RES_LEN
] = {0};
645 res
= CIPURSESelect(true, true, buf
, sizeof(buf
), &len
, &sw
);
646 if (res
!= 0 || sw
!= 0x9000) {
647 PrintAndLogEx(ERR
, "Cipurse select " _RED_("error") ". Card returns 0x%04x", sw
);
653 PrintAndLogEx(INFO
, "File id " _YELLOW_("%x") " key id " _YELLOW_("%d") " key " _YELLOW_("%s")
656 , sprint_hex(key
, CIPURSE_AES_KEY_LENGTH
)
660 bool bres
= CIPURSEChannelAuthenticate(keyId
, key
, verbose
);
662 if (verbose
== false)
663 PrintAndLogEx(ERR
, "Authentication ( " _RED_("fail") " )");
668 // set channel security levels
669 CIPURSECSetActChannelSecurityLevels(sreq
, sresp
);
671 res
= CIPURSEDeleteFile(fileId
, buf
, sizeof(buf
), &len
, &sw
);
672 if (res
!= 0 || sw
!= 0x9000) {
673 if (verbose
== false)
674 PrintAndLogEx(ERR
, "File select " _RED_("ERROR") ". Card returns 0x%04x", sw
);
679 PrintAndLogEx(INFO
, "File id " _YELLOW_("%04x") " deleted " _GREEN_("succesfully"), fileId
);
686 bool CheckCardCipurse(void) {
687 uint8_t buf
[APDU_RES_LEN
] = {0};
690 int res
= CIPURSESelect(true, false, buf
, sizeof(buf
), &len
, &sw
);
692 return (res
== 0 && sw
== 0x9000);
695 static command_t CommandTable
[] = {
696 {"help", CmdHelp
, AlwaysAvailable
, "This help."},
697 {"info", CmdHFCipurseInfo
, IfPm3Iso14443a
, "Get info about CIPURSE tag"},
698 {"auth", CmdHFCipurseAuth
, IfPm3Iso14443a
, "Authenticate CIPURSE tag"},
699 {"read", CmdHFCipurseReadFile
, IfPm3Iso14443a
, "Read binary file"},
700 {"write", CmdHFCipurseWriteFile
, IfPm3Iso14443a
, "Write binary file"},
701 {"aread", CmdHFCipurseReadFileAttr
, IfPm3Iso14443a
, "Read file attributes"},
702 {"delete", CmdHFCipurseDeleteFile
, IfPm3Iso14443a
, "Delete file"},
703 {NULL
, NULL
, 0, NULL
}
706 int CmdHFCipurse(const char *Cmd
) {
707 clearCommandBuffer();
708 return CmdsParse(CommandTable
, Cmd
);
711 int CmdHelp(const char *Cmd
) {
712 (void)Cmd
; // Cmd is not used so far
713 CmdsHelp(CommandTable
);