60 #endif // HAVE_CONFIG_H
62 #include <sys/types.h>
80 static bool quiet_output =
false;
82 static int type4v = 2;
84 #define SYMBOL_PARAM_fISO14443_4_PICC 0x20
86 typedef enum { NONE, CC_FILE, NDEF_FILE } file;
88 struct nfcforum_tag4_ndef_data {
93 struct nfcforum_tag4_state_machine_data {
97 uint8_t nfcforum_capability_container[] = {
123 #define ISO144434A_RATS 0xE0
126 nfcforum_tag4_io(
struct nfc_emulator *emulator,
const uint8_t *data_in,
const size_t data_in_len, uint8_t *data_out,
const size_t data_out_len)
130 struct nfcforum_tag4_ndef_data *ndef_data = (
struct nfcforum_tag4_ndef_data *)(emulator->user_data);
131 struct nfcforum_tag4_state_machine_data *state_machine_data = (
struct nfcforum_tag4_state_machine_data *)(emulator->state_machine->data);
133 if (data_in_len == 0) {
141 print_hex(data_in, data_in_len);
144 if (data_in_len >= 4) {
145 if (data_in[CLA] != 0x00)
148 #define ISO7816_SELECT 0xA4
149 #define ISO7816_READ_BINARY 0xB0
150 #define ISO7816_UPDATE_BINARY 0xD6
152 switch (data_in[INS]) {
155 switch (data_in[P1]) {
157 if ((data_in[P2] | 0x0C) != 0x0C)
160 const uint8_t ndef_capability_container[] = { 0xE1, 0x03 };
161 const uint8_t ndef_file[] = { 0xE1, 0x04 };
162 if ((data_in[LC] ==
sizeof(ndef_capability_container)) && (0 == memcmp(ndef_capability_container, data_in + DATA, data_in[LC]))) {
163 memcpy(data_out,
"\x90\x00", res = 2);
164 state_machine_data->current_file = CC_FILE;
165 }
else if ((data_in[LC] ==
sizeof(ndef_file)) && (0 == memcmp(ndef_file, data_in + DATA, data_in[LC]))) {
166 memcpy(data_out,
"\x90\x00", res = 2);
167 state_machine_data->current_file = NDEF_FILE;
169 memcpy(data_out,
"\x6a\x00", res = 2);
170 state_machine_data->current_file = NONE;
175 if (data_in[P2] != 0x00)
178 const uint8_t ndef_tag_application_name_v1[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 };
179 const uint8_t ndef_tag_application_name_v2[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
180 if ((type4v == 1) && (data_in[LC] ==
sizeof(ndef_tag_application_name_v1)) && (0 == memcmp(ndef_tag_application_name_v1, data_in + DATA, data_in[LC])))
181 memcpy(data_out,
"\x90\x00", res = 2);
182 else if ((type4v == 2) && (data_in[LC] ==
sizeof(ndef_tag_application_name_v2)) && (0 == memcmp(ndef_tag_application_name_v2, data_in + DATA, data_in[LC])))
183 memcpy(data_out,
"\x90\x00", res = 2);
185 memcpy(data_out,
"\x6a\x82", res = 2);
193 case ISO7816_READ_BINARY:
194 if ((
size_t)(data_in[LC] + 2) > data_out_len) {
197 switch (state_machine_data->current_file) {
199 memcpy(data_out,
"\x6a\x82", res = 2);
202 memcpy(data_out, nfcforum_capability_container + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
203 memcpy(data_out + data_in[LC],
"\x90\x00", 2);
204 res = data_in[LC] + 2;
207 memcpy(data_out, ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
208 memcpy(data_out + data_in[LC],
"\x90\x00", 2);
209 res = data_in[LC] + 2;
214 case ISO7816_UPDATE_BINARY:
215 memcpy(ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in + DATA, data_in[LC]);
216 if ((data_in[P1] << 8) + data_in[P2] == 0) {
217 ndef_data->ndef_file_len = (ndef_data->ndef_file[0] << 8) + ndef_data->ndef_file[1] + 2;
219 memcpy(data_out,
"\x90\x00", res = 2);
223 printf(
"Unknown frame, emulated target abort.\n");
234 ERR(
"%s (%d)", strerror(-res), -res);
237 print_hex(data_out, res);
243 static void stop_emulation(
int sig)
255 ndef_message_load(
char *filename,
struct nfcforum_tag4_ndef_data *tag_data)
259 if (!(F = fopen(filename,
"r"))) {
260 printf(
"File not found or not accessible '%s'\n", filename);
263 if (stat(filename, &sb) < 0) {
264 printf(
"File not found or not accessible '%s'\n", filename);
270 if (sb.st_size > 0xFFFF) {
271 printf(
"File size too large '%s'\n", filename);
276 tag_data->ndef_file_len = sb.st_size + 2;
278 tag_data->ndef_file[0] = (uint8_t)(sb.st_size >> 8);
279 tag_data->ndef_file[1] = (uint8_t)(sb.st_size);
282 if (1 != fread(tag_data->ndef_file + 2, sb.st_size, 1, F)) {
283 printf(
"Can't read from %s\n", filename);
293 ndef_message_save(
char *filename,
struct nfcforum_tag4_ndef_data *tag_data)
296 if (!(F = fopen(filename,
"w"))) {
297 printf(
"fopen (%s, w)\n", filename);
301 if (1 != fwrite(tag_data->ndef_file + 2, tag_data->ndef_file_len - 2, 1, F)) {
302 printf(
"fwrite (%d)\n", (
int) tag_data->ndef_file_len - 2);
308 return tag_data->ndef_file_len - 2;
312 usage(
char *progname)
314 fprintf(stderr,
"usage: %s [-1] [infile [outfile]]\n", progname);
315 fprintf(stderr,
" -1: force Tag Type 4 v1.0 (default is v2.0)\n");
319 main(
int argc,
char *argv[])
324 .nmt = NMT_ISO14443A,
325 .nbr = NBR_UNDEFINED,
329 .abtAtqa = { 0x00, 0x04 },
330 .abtUid = { 0x08, 0x00, 0xb0, 0x0b },
333 .abtAts = { 0x75, 0x33, 0x92, 0x03 },
339 uint8_t ndef_file[0xfffe] = {
341 0xd1, 0x02, 0x1c, 0x53, 0x70, 0x91, 0x01, 0x09, 0x54, 0x02,
342 0x65, 0x6e, 0x4c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x51, 0x01,
343 0x0b, 0x55, 0x03, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x2e,
347 struct nfcforum_tag4_ndef_data nfcforum_tag4_data = {
348 .ndef_file = ndef_file,
349 .ndef_file_len = ndef_file[1] + 2,
352 struct nfcforum_tag4_state_machine_data state_machine_data = {
353 .current_file = NONE,
357 .io = nfcforum_tag4_io,
358 .data = &state_machine_data,
363 .state_machine = &state_machine,
364 .user_data = &nfcforum_tag4_data,
367 if ((argc > (1 + options)) && (0 == strcmp(
"-h", argv[1 + options]))) {
372 if ((argc > (1 + options)) && (0 == strcmp(
"-1", argv[1 + options]))) {
374 nfcforum_capability_container[2] = 0x10;
378 if (argc > (3 + options)) {
384 if (argc >= (2 + options)) {
385 if (ndef_message_load(argv[1 + options], &nfcforum_tag4_data) < 0) {
386 printf(
"Can't load NDEF file '%s'\n", argv[1 + options]);
392 if (context == NULL) {
393 ERR(
"Unable to init libnfc (malloc)\n");
401 ERR(
"Unable to open NFC device");
406 signal(SIGINT, stop_emulation);
409 printf(
"Emulating NDEF tag now, please touch it with a second NFC device\n");
418 if (argc == (3 + options)) {
419 if (ndef_message_save(argv[2 + options], &nfcforum_tag4_data) < 0) {
420 printf(
"Can't save NDEF file '%s'", argv[2 + options]);