Merge pull request #2654 from Antiklesys/master
[RRG-proxmark3.git] / client / src / mifare / aiddesfire.c
blobf1d7609f7a8a0a2a21b4d0d03a296361cf1715b2
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // AID DESFire functions
17 //-----------------------------------------------------------------------------
19 #include "aiddesfire.h"
20 #include "pm3_cmd.h"
21 #include "fileutils.h"
22 #include "jansson.h"
24 // NXP Appnote AN10787 - Application Directory (MAD)
25 typedef enum {
26 CL_ADMIN = 0,
27 CL_MISC1,
28 CL_MISC2,
29 CL_MISC3,
30 CL_MISC4,
31 CL_MISC5,
32 CL_MISC6,
33 CL_MISC7,
34 CL_AIRLINES = 8,
35 CL_FERRY,
36 CL_RAIL,
37 CL_MISC,
38 CL_TRANSPORT,
39 CL_SECURITY = 0x14,
40 CL_CITYTRAFFIC = 0x18,
41 CL_CZECH_RAIL,
42 CL_BUS,
43 CL_MMT,
44 CL_TAXI = 0x28,
45 CL_TOLL = 0x30,
46 CL_GENERIC_TRANS,
47 CL_COMPANY_SERVICES = 0x38,
48 CL_CITYCARD = 0x40,
49 CL_ACCESS_CONTROL_1 = 0x47,
50 CL_ACCESS_CONTROL_2,
51 CL_VIGIK = 0x49,
52 CL_NED_DEFENCE = 0x4A,
53 CL_BOSCH_TELECOM = 0x4B,
54 CL_EU = 0x4C,
55 CL_SKI_TICKET = 0x50,
56 CL_SOAA = 0x55,
57 CL_ACCESS2 = 0x56,
58 CL_FOOD = 0x60,
59 CL_NONFOOD = 0x68,
60 CL_HOTEL = 0x70,
61 CL_LOYALTY = 0x71,
62 CL_AIRPORT = 0x75,
63 CL_CAR_RENTAL = 0x78,
64 CL_NED_GOV = 0x79,
65 CL_ADMIN2 = 0x80,
66 CL_PURSE = 0x88,
67 CL_TV = 0x90,
68 CL_CRUISESHIP = 0x91,
69 CL_IOPTA = 0x95,
70 CL_METERING = 0x97,
71 CL_TELEPHONE = 0x98,
72 CL_HEALTH = 0xA0,
73 CL_WAREHOUSE = 0xA8,
74 CL_BANKING = 0xB8,
75 CL_ENTERTAIN = 0xC0,
76 CL_PARKING = 0xC8,
77 CL_FLEET = 0xC9,
78 CL_FUEL = 0xD0,
79 CL_INFO = 0xD8,
80 CL_PRESS = 0xE0,
81 CL_NFC = 0xE1,
82 CL_COMPUTER = 0xE8,
83 CL_MAIL = 0xF0,
84 CL_AMISC = 0xF8,
85 CL_AMISC1 = 0xF9,
86 CL_AMISC2 = 0xFA,
87 CL_AMISC3 = 0xFB,
88 CL_AMISC4 = 0xFC,
89 CL_AMISC5 = 0xFD,
90 CL_AMISC6 = 0xFE,
91 CL_AMISC7 = 0xFF,
92 } aidcluster_h;
94 const char *nxp_cluster_to_text(uint8_t cluster) {
95 switch (cluster) {
96 case CL_ADMIN:
97 return "card administration";
98 case CL_MISC1:
99 case CL_MISC2:
100 case CL_MISC3:
101 case CL_MISC4:
102 case CL_MISC5:
103 case CL_MISC6:
104 case CL_MISC7:
105 return "miscellaneous applications";
106 case CL_AIRLINES:
107 return "airlines";
108 case CL_FERRY:
109 return "ferry traffic";
110 case CL_RAIL:
111 return "railway services";
112 case CL_MISC:
113 return "miscellaneous applications";
114 case CL_TRANSPORT:
115 return "transport";
116 case CL_SECURITY:
117 return "security solutions";
118 case CL_CITYTRAFFIC:
119 return "city traffic";
120 case CL_CZECH_RAIL:
121 return "Czech Railways";
122 case CL_BUS:
123 return "bus services";
124 case CL_MMT:
125 return "multi modal transit";
126 case CL_TAXI:
127 return "taxi";
128 case CL_TOLL:
129 return "road toll";
130 case CL_GENERIC_TRANS:
131 return "generic transport";
132 case CL_COMPANY_SERVICES:
133 return "company services";
134 case CL_CITYCARD:
135 return "city card services";
136 case CL_ACCESS_CONTROL_1:
137 case CL_ACCESS_CONTROL_2:
138 return "access control & security";
139 case CL_VIGIK:
140 return "VIGIK";
141 case CL_NED_DEFENCE:
142 return "Ministry of Defence, Netherlands";
143 case CL_BOSCH_TELECOM:
144 return "Bosch Telecom, Germany";
145 case CL_EU:
146 return "European Union Institutions";
147 case CL_SKI_TICKET:
148 return "ski ticketing";
149 case CL_SOAA:
150 return "SOAA standard for offline access standard";
151 case CL_ACCESS2:
152 return "access control & security";
153 case CL_FOOD:
154 return "food";
155 case CL_NONFOOD:
156 return "non-food trade";
157 case CL_HOTEL:
158 return "hotel";
159 case CL_LOYALTY:
160 return "loyalty";
161 case CL_AIRPORT:
162 return "airport services";
163 case CL_CAR_RENTAL:
164 return "car rental";
165 case CL_NED_GOV:
166 return "Dutch government";
167 case CL_ADMIN2:
168 return "administration services";
169 case CL_PURSE:
170 return "electronic purse";
171 case CL_TV:
172 return "television";
173 case CL_CRUISESHIP:
174 return "cruise ship";
175 case CL_IOPTA:
176 return "IOPTA";
177 case CL_METERING:
178 return "metering";
179 case CL_TELEPHONE:
180 return "telephone";
181 case CL_HEALTH:
182 return "health services";
183 case CL_WAREHOUSE:
184 return "warehouse";
185 case CL_BANKING:
186 return "banking";
187 case CL_ENTERTAIN:
188 return "entertainment & sports";
189 case CL_PARKING:
190 return "car parking";
191 case CL_FLEET:
192 return "fleet management";
193 case CL_FUEL:
194 return "fuel, gasoline";
195 case CL_INFO:
196 return "info services";
197 case CL_PRESS:
198 return "press";
199 case CL_NFC:
200 return "NFC Forum";
201 case CL_COMPUTER:
202 return "computer";
203 case CL_MAIL:
204 return "mail";
205 case CL_AMISC:
206 case CL_AMISC1:
207 case CL_AMISC2:
208 case CL_AMISC3:
209 case CL_AMISC4:
210 case CL_AMISC5:
211 case CL_AMISC6:
212 case CL_AMISC7:
213 return "miscellaneous applications";
214 default:
215 break;
217 return "reserved";
220 static json_t *df_known_aids = NULL;
222 static int open_aiddf_file(json_t **root, bool verbose) {
224 char *path;
225 int res = searchFile(&path, RESOURCES_SUBDIR, "aid_desfire", ".json", true);
226 if (res != PM3_SUCCESS) {
227 return PM3_EFILE;
230 int retval = PM3_SUCCESS;
231 json_error_t error;
233 *root = json_load_file(path, 0, &error);
234 if (!*root) {
235 PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text);
236 retval = PM3_ESOFT;
237 goto out;
240 if (!json_is_array(*root)) {
241 PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path);
242 retval = PM3_ESOFT;
243 goto out;
246 if (verbose) {
247 PrintAndLogEx(SUCCESS, "Loaded file `" _YELLOW_("%s") "` " _GREEN_("%zu") " records ( " _GREEN_("ok") " )"
248 , path
249 , json_array_size(*root)
253 out:
254 free(path);
255 return retval;
258 static int close_aiddf_file(json_t *root) {
259 json_decref(root);
260 return PM3_SUCCESS;
263 static const char *aiddf_json_get_str(json_t *data, const char *name) {
265 json_t *jstr = json_object_get(data, name);
266 if (jstr == NULL)
267 return NULL;
269 if (!json_is_string(jstr)) {
270 PrintAndLogEx(WARNING, _YELLOW_("`%s`") " is not a string", name);
271 return NULL;
274 const char *cstr = json_string_value(jstr);
275 if (strlen(cstr) == 0)
276 return NULL;
278 return cstr;
281 static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool verbose) {
282 char laid[7] = {0};
283 snprintf(laid, sizeof(laid), "%02x%02x%02x", aid[2], aid[1], aid[0]); // must be lowercase
285 json_t *elm = NULL;
287 for (uint32_t idx = 0; idx < json_array_size(root); idx++) {
288 json_t *data = json_array_get(root, idx);
289 if (!json_is_object(data)) {
290 PrintAndLogEx(ERR, "data [%d] is not an object\n", idx);
291 continue;
293 const char *faid = aiddf_json_get_str(data, "AID");
294 char lfaid[strlen(faid) + 1];
295 strcpy(lfaid, faid);
296 str_lower(lfaid);
297 if (strcmp(laid, lfaid) == 0) {
298 elm = data;
299 break;
303 if (elm == NULL) {
304 PrintAndLogEx(INFO, fmt, " (unknown)");
305 return PM3_ENODATA;
307 const char *vaid = aiddf_json_get_str(elm, "AID");
308 const char *vendor = aiddf_json_get_str(elm, "Vendor");
309 const char *country = aiddf_json_get_str(elm, "Country");
310 const char *name = aiddf_json_get_str(elm, "Name");
311 const char *description = aiddf_json_get_str(elm, "Description");
312 const char *type = aiddf_json_get_str(elm, "Type");
314 if (name && vendor) {
315 size_t result_len = 5 + strlen(name) + strlen(vendor);
316 char result[result_len];
317 snprintf(result, result_len, " %s [%s]", name, vendor);
318 PrintAndLogEx(INFO, fmt, result);
321 if (verbose) {
322 PrintAndLogEx(SUCCESS, " AID: %s", vaid);
323 if (name)
324 PrintAndLogEx(SUCCESS, " Name: %s", name);
325 if (description)
326 PrintAndLogEx(SUCCESS, " Description: %s", description);
327 if (type)
328 PrintAndLogEx(SUCCESS, " Type: %s", type);
329 if (vendor)
330 PrintAndLogEx(SUCCESS, " Vendor: %s", vendor);
331 if (country)
332 PrintAndLogEx(SUCCESS, " Country: %s", country);
334 return PM3_SUCCESS;
337 int AIDDFDecodeAndPrint(uint8_t aid[3]) {
338 open_aiddf_file(&df_known_aids, false);
340 char fmt[80];
341 snprintf(fmt, sizeof(fmt), " DF AID Function... %02X%02X%02X :" _YELLOW_("%s"), aid[2], aid[1], aid[0], "%s");
342 print_aiddf_description(df_known_aids, aid, fmt, false);
343 close_aiddf_file(df_known_aids);
344 return PM3_SUCCESS;