fix little endian vs big endian in the macros... again... but this time correct
[RRG-proxmark3.git] / client / src / cmdhfthinfilm.c
blob0630fe6205f0dcb8e40437479d489b09575f0ff2
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2019 iceman
3 //
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
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Thinfilm commands
9 //-----------------------------------------------------------------------------
10 #include "cmdhfthinfilm.h"
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include "cliparser.h"
16 #include "cmdparser.h" // command_t
17 #include "comms.h"
18 #include "cmdtrace.h"
19 #include "crc16.h"
20 #include "ui.h"
21 #include "cmdhf14a.h" // manufacture
23 static int CmdHelp(const char *Cmd);
25 // Printing function based upon the code in libnfc
26 // ref
27 // https://github.com/nfc-tools/libnfc/blob/master/utils/nfc-barcode.c
28 static int print_barcode(uint8_t *barcode, const size_t barcode_len, bool verbose) {
30 PrintAndLogEx(NORMAL, "");
31 // remove start bit
32 uint8_t mb = barcode[0] & ~0x80;
33 PrintAndLogEx(SUCCESS, " Manufacturer : "_YELLOW_("%s") "[0x%02X]", getTagInfo(mb), mb);
35 if (verbose) {
36 PrintAndLogEx(SUCCESS, " Data format : "_YELLOW_("%02X"), barcode[1]);
37 if (barcode_len > 2) {
38 uint8_t b1, b2;
39 compute_crc(CRC_14443_A, barcode, barcode_len - 2, &b1, &b2);
40 bool isok = (barcode[barcode_len - 1] == b1 && barcode[barcode_len - 2] == b2);
42 PrintAndLogEx(SUCCESS, " Checksum : "_YELLOW_("%02X %02X")" - %s", b2, b1, (isok) ? _GREEN_("OK") : _RED_("fail"));
43 } else {
44 PrintAndLogEx(SUCCESS, " Checksum : "_YELLOW_("too few data for checksum")" - " _RED_("fail"));
46 PrintAndLogEx(SUCCESS, " Data len (bits) : "_YELLOW_("%zu")" - %s", barcode_len * 8, (barcode_len == 16 || barcode_len == 32) ? _GREEN_("OK") : _YELLOW_("warning"));
47 PrintAndLogEx(SUCCESS, " Raw data : "_YELLOW_("%s"), sprint_hex(barcode, barcode_len));
48 if (barcode_len < 4) // too few to go to next decoding stages
49 return PM3_ESOFT;
52 char s[45];
53 memset(s, 0x00, sizeof(s));
55 switch (barcode[1]) {
56 case 0:
57 PrintAndLogEx(SUCCESS, " Data format : Reserved for allocation by tag manufacturer");
58 return PM3_SUCCESS;
59 case 1:
60 snprintf(s, sizeof(s), "http://www.");
61 break;
62 case 2:
63 snprintf(s, sizeof(s), "https://www.");
64 break;
65 case 3:
66 snprintf(s, sizeof(s), "http://");
67 break;
68 case 4:
69 snprintf(s, sizeof(s), "https://");
70 break;
71 case 5:
72 if (barcode_len < 16) {
73 PrintAndLogEx(WARNING, "EPC: (partial data) %s", sprint_hex(barcode + 2, barcode_len - 2));
74 return PM3_ESOFT;
76 PrintAndLogEx(SUCCESS, "EPC: %s", sprint_hex(barcode + 2, 12));
77 return PM3_SUCCESS;
78 default:
79 PrintAndLogEx(SUCCESS, " Data format : RFU Reserved for future use (%02X)", barcode[1]);
80 if (!verbose)
81 PrintAndLogEx(SUCCESS, "Raw data with CRC: "_YELLOW_("%s"), sprint_hex(barcode, barcode_len));
82 return PM3_SUCCESS;
85 snprintf(s + strlen(s), barcode_len - 3, (const char *)&barcode[2], barcode_len - 4);
87 for (uint8_t i = 0; i < strlen(s); i++) {
89 // terminate string
90 if ((uint8_t) s[i] == 0xFE) {
91 s[i] = 0;
92 break;
95 PrintAndLogEx(SUCCESS, " Decoded NFC URL : "_YELLOW_("%s"), s);
96 return PM3_SUCCESS;
99 int CmdHfThinFilmInfo(const char *Cmd) {
100 CLIParserContext *ctx;
101 CLIParserInit(&ctx, "hf thinfilm info",
102 "Get info from Thinfilm tags",
103 "hf thinfilm info");
105 void *argtable[] = {
106 arg_param_begin,
107 arg_param_end
109 CLIExecWithReturn(ctx, Cmd, argtable, true);
110 CLIParserFree(ctx);
111 return infoThinFilm(true);
114 int infoThinFilm(bool verbose) {
116 clearCommandBuffer();
117 SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0);
119 PacketResponseNG resp;
120 if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) {
121 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
122 return PM3_ETIMEOUT;
125 if (resp.status == PM3_SUCCESS) {
126 if (resp.length == 16 || resp.length == 32) {
127 PrintAndLogEx(NORMAL, "");
128 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
129 print_barcode(resp.data.asBytes, resp.length, verbose);
130 } else {
131 if (verbose)
132 PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length);
134 return PM3_ESOFT;
138 return resp.status;
141 int CmdHfThinFilmSim(const char *Cmd) {
142 CLIParserContext *ctx;
143 CLIParserInit(&ctx, "hf thinfilm sim",
144 "Simulate Thinfilm tag",
145 "hf thinfilm sim -d B70470726f786d61726b2e636f6d");
147 void *argtable[] = {
148 arg_param_begin,
149 arg_str1("d", "data", "<hex>", "bytes to send"),
150 arg_lit0(NULL, "raw", "raw, provided bytes should include CRC"),
151 arg_param_end
153 CLIExecWithReturn(ctx, Cmd, argtable, false);
155 int data_len = 0;
156 uint8_t data[512] = {0};
157 CLIGetHexWithReturn(ctx, 1, data, &data_len);
159 bool addcrc = true;
161 if (arg_get_lit(ctx, 2)) {
162 addcrc = false;
165 CLIParserFree(ctx);
167 if (addcrc && data_len <= 510) {
168 uint8_t b1, b2;
169 compute_crc(CRC_14443_A, data, data_len, &b1, &b2);
170 data[data_len++] = b2;
171 data[data_len++] = b1;
174 clearCommandBuffer();
175 SendCommandNG(CMD_HF_THINFILM_SIMULATE, (uint8_t *)&data, data_len);
176 PacketResponseNG resp;
177 PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation");
179 int ret;
180 while (!(ret = kbd_enter_pressed())) {
181 if (WaitForResponseTimeout(CMD_HF_THINFILM_SIMULATE, &resp, 500) == 0) continue;
182 if (resp.status != PM3_SUCCESS) break;
184 if (ret) {
185 PrintAndLogEx(INFO, "Client side interrupted");
186 PrintAndLogEx(WARNING, "Simulation still running on Proxmark3 till next command or button press");
187 } else {
188 PrintAndLogEx(INFO, "Done");
190 return PM3_SUCCESS;
193 static int CmdHfThinFilmList(const char *Cmd) {
194 return CmdTraceListAlias(Cmd, "hf thinfilm", "thinfilm");
197 static command_t CommandTable[] = {
198 {"help", CmdHelp, AlwaysAvailable, "This help"},
199 {"info", CmdHfThinFilmInfo, IfPm3NfcBarcode, "Tag information"},
200 {"list", CmdHfThinFilmList, AlwaysAvailable, "List NFC Barcode / Thinfilm history - not correct"},
201 {"sim", CmdHfThinFilmSim, IfPm3NfcBarcode, "Fake Thinfilm tag"},
202 {NULL, NULL, NULL, NULL}
205 static int CmdHelp(const char *Cmd) {
206 (void)Cmd; // Cmd is not used so far
207 CmdsHelp(CommandTable);
208 return PM3_SUCCESS;
211 int CmdHFThinfilm(const char *Cmd) {
212 clearCommandBuffer();
213 return CmdsParse(CommandTable, Cmd);