59 #endif // HAVE_CONFIG_H
61 #include <sys/types.h>
79 static bool quiet_output =
false;
81 static int type4v = 2;
83 #define SYMBOL_PARAM_fISO14443_4_PICC 0x20
85 typedef enum { NONE, CC_FILE, NDEF_FILE } file;
87 struct nfcforum_tag4_ndef_data {
92 struct nfcforum_tag4_state_machine_data {
96 uint8_t nfcforum_capability_container[] = {
122 #define ISO144434A_RATS 0xE0
125 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)
129 struct nfcforum_tag4_ndef_data *ndef_data = (
struct nfcforum_tag4_ndef_data *)(emulator->user_data);
130 struct nfcforum_tag4_state_machine_data *state_machine_data = (
struct nfcforum_tag4_state_machine_data *)(emulator->state_machine->data);
132 if (data_in_len == 0) {
140 print_hex(data_in, data_in_len);
143 if (data_in_len >= 4) {
144 if (data_in[CLA] != 0x00)
147 #define ISO7816_SELECT 0xA4
148 #define ISO7816_READ_BINARY 0xB0
149 #define ISO7816_UPDATE_BINARY 0xD6
151 switch (data_in[INS]) {
154 switch (data_in[P1]) {
156 if ((data_in[P2] | 0x0C) != 0x0C)
159 const uint8_t ndef_capability_container[] = { 0xE1, 0x03 };
160 const uint8_t ndef_file[] = { 0xE1, 0x04 };
161 if ((data_in[LC] ==
sizeof(ndef_capability_container)) && (0 == memcmp(ndef_capability_container, data_in + DATA, data_in[LC]))) {
162 memcpy(data_out,
"\x90\x00", res = 2);
163 state_machine_data->current_file = CC_FILE;
164 }
else if ((data_in[LC] ==
sizeof(ndef_file)) && (0 == memcmp(ndef_file, data_in + DATA, data_in[LC]))) {
165 memcpy(data_out,
"\x90\x00", res = 2);
166 state_machine_data->current_file = NDEF_FILE;
168 memcpy(data_out,
"\x6a\x00", res = 2);
169 state_machine_data->current_file = NONE;
174 if (data_in[P2] != 0x00)
177 const uint8_t ndef_tag_application_name_v1[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 };
178 const uint8_t ndef_tag_application_name_v2[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 };
179 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])))
180 memcpy(data_out,
"\x90\x00", res = 2);
181 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])))
182 memcpy(data_out,
"\x90\x00", res = 2);
184 memcpy(data_out,
"\x6a\x82", res = 2);
192 case ISO7816_READ_BINARY:
193 if ((
size_t)(data_in[LC] + 2) > data_out_len) {
196 switch (state_machine_data->current_file) {
198 memcpy(data_out,
"\x6a\x82", res = 2);
201 memcpy(data_out, nfcforum_capability_container + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
202 memcpy(data_out + data_in[LC],
"\x90\x00", 2);
203 res = data_in[LC] + 2;
206 memcpy(data_out, ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
207 memcpy(data_out + data_in[LC],
"\x90\x00", 2);
208 res = data_in[LC] + 2;
213 case ISO7816_UPDATE_BINARY:
214 memcpy(ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in + DATA, data_in[LC]);
215 if ((data_in[P1] << 8) + data_in[P2] == 0) {
216 ndef_data->ndef_file_len = (ndef_data->ndef_file[0] << 8) + ndef_data->ndef_file[1] + 2;
218 memcpy(data_out,
"\x90\x00", res = 2);
222 printf(
"Unknown frame, emulated target abort.\n");
233 ERR(
"%s (%d)", strerror(-res), -res);
236 print_hex(data_out, res);
242 static void stop_emulation(
int sig)
254 ndef_message_load(
char *filename,
struct nfcforum_tag4_ndef_data *tag_data)
257 if (stat(filename, &sb) < 0) {
258 printf(
"file not found or not accessible '%s'", filename);
263 if (sb.st_size > 0xFFFF) {
264 printf(
"file size too large '%s'", filename);
268 tag_data->ndef_file_len = sb.st_size + 2;
270 tag_data->ndef_file[0] = (uint8_t)(sb.st_size >> 8);
271 tag_data->ndef_file[1] = (uint8_t)(sb.st_size);
274 if (!(F = fopen(filename,
"r"))) {
275 printf(
"fopen (%s, \"r\")", filename);
279 if (1 != fread(tag_data->ndef_file + 2, sb.st_size, 1, F)) {
280 printf(
"Can't read from %s", filename);
290 ndef_message_save(
char *filename,
struct nfcforum_tag4_ndef_data *tag_data)
293 if (!(F = fopen(filename,
"w"))) {
294 printf(
"fopen (%s, w)", filename);
298 if (1 != fwrite(tag_data->ndef_file + 2, tag_data->ndef_file_len - 2, 1, F)) {
299 printf(
"fwrite (%d)", (
int) tag_data->ndef_file_len - 2);
305 return tag_data->ndef_file_len - 2;
309 usage(
char *progname)
311 fprintf(stderr,
"usage: %s [-1] [infile [outfile]]\n", progname);
312 fprintf(stderr,
" -1: force Tag Type 4 v1.0 (default is v2.0)\n");
316 main(
int argc,
char *argv[])
321 .nmt = NMT_ISO14443A,
322 .nbr = NBR_UNDEFINED,
326 .abtAtqa = { 0x00, 0x04 },
327 .abtUid = { 0x08, 0x00, 0xb0, 0x0b },
330 .abtAts = { 0x75, 0x33, 0x92, 0x03 },
336 uint8_t ndef_file[0xfffe] = {
338 0xd1, 0x02, 0x1c, 0x53, 0x70, 0x91, 0x01, 0x09, 0x54, 0x02,
339 0x65, 0x6e, 0x4c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x51, 0x01,
340 0x0b, 0x55, 0x03, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x2e,
344 struct nfcforum_tag4_ndef_data nfcforum_tag4_data = {
345 .ndef_file = ndef_file,
346 .ndef_file_len = ndef_file[1] + 2,
349 struct nfcforum_tag4_state_machine_data state_machine_data = {
350 .current_file = NONE,
354 .io = nfcforum_tag4_io,
355 .data = &state_machine_data,
360 .state_machine = &state_machine,
361 .user_data = &nfcforum_tag4_data,
364 if ((argc > (1 + options)) && (0 == strcmp(
"-h", argv[1 + options]))) {
369 if ((argc > (1 + options)) && (0 == strcmp(
"-1", argv[1 + options]))) {
371 nfcforum_capability_container[2] = 0x10;
375 if (argc > (3 + options)) {
381 if (argc >= (2 + options)) {
382 if (ndef_message_load(argv[1 + options], &nfcforum_tag4_data) < 0) {
383 printf(
"Can't load NDEF file '%s'", argv[1 + options]);
389 if (context == NULL) {
390 ERR(
"Unable to init libnfc (malloc)\n");
398 ERR(
"Unable to open NFC device");
403 signal(SIGINT, stop_emulation);
406 printf(
"Emulating NDEF tag now, please touch it with a second NFC device\n");
415 if (argc == (3 + options)) {
416 if (ndef_message_save(argv[2 + options], &nfcforum_tag4_data) < 0) {
417 printf(
"Can't save NDEF file '%s'", argv[2 + options]);