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)
258 if (stat(filename, &sb) < 0) {
259 printf(
"file not found or not accessible '%s'", filename);
264 if (sb.st_size > 0xFFFF) {
265 printf(
"file size too large '%s'", filename);
269 tag_data->ndef_file_len = sb.st_size + 2;
271 tag_data->ndef_file[0] = (uint8_t)(sb.st_size >> 8);
272 tag_data->ndef_file[1] = (uint8_t)(sb.st_size);
275 if (!(F = fopen(filename,
"r"))) {
276 printf(
"fopen (%s, \"r\")", filename);
280 if (1 != fread(tag_data->ndef_file + 2, sb.st_size, 1, F)) {
281 printf(
"Can't read from %s", filename);
291 ndef_message_save(
char *filename,
struct nfcforum_tag4_ndef_data *tag_data)
294 if (!(F = fopen(filename,
"w"))) {
295 printf(
"fopen (%s, w)", filename);
299 if (1 != fwrite(tag_data->ndef_file + 2, tag_data->ndef_file_len - 2, 1, F)) {
300 printf(
"fwrite (%d)", (
int) tag_data->ndef_file_len - 2);
306 return tag_data->ndef_file_len - 2;
310 usage(
char *progname)
312 fprintf(stderr,
"usage: %s [-1] [infile [outfile]]\n", progname);
313 fprintf(stderr,
" -1: force Tag Type 4 v1.0 (default is v2.0)\n");
317 main(
int argc,
char *argv[])
322 .nmt = NMT_ISO14443A,
323 .nbr = NBR_UNDEFINED,
327 .abtAtqa = { 0x00, 0x04 },
328 .abtUid = { 0x08, 0x00, 0xb0, 0x0b },
331 .abtAts = { 0x75, 0x33, 0x92, 0x03 },
337 uint8_t ndef_file[0xfffe] = {
339 0xd1, 0x02, 0x1c, 0x53, 0x70, 0x91, 0x01, 0x09, 0x54, 0x02,
340 0x65, 0x6e, 0x4c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x51, 0x01,
341 0x0b, 0x55, 0x03, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x2e,
345 struct nfcforum_tag4_ndef_data nfcforum_tag4_data = {
346 .ndef_file = ndef_file,
347 .ndef_file_len = ndef_file[1] + 2,
350 struct nfcforum_tag4_state_machine_data state_machine_data = {
351 .current_file = NONE,
355 .io = nfcforum_tag4_io,
356 .data = &state_machine_data,
361 .state_machine = &state_machine,
362 .user_data = &nfcforum_tag4_data,
365 if ((argc > (1 + options)) && (0 == strcmp(
"-h", argv[1 + options]))) {
370 if ((argc > (1 + options)) && (0 == strcmp(
"-1", argv[1 + options]))) {
372 nfcforum_capability_container[2] = 0x10;
376 if (argc > (3 + options)) {
382 if (argc >= (2 + options)) {
383 if (ndef_message_load(argv[1 + options], &nfcforum_tag4_data) < 0) {
384 printf(
"Can't load NDEF file '%s'", argv[1 + options]);
390 if (context == NULL) {
391 ERR(
"Unable to init libnfc (malloc)\n");
399 ERR(
"Unable to open NFC device");
404 signal(SIGINT, stop_emulation);
407 printf(
"Emulating NDEF tag now, please touch it with a second NFC device\n");
416 if (argc == (3 + options)) {
417 if (ndef_message_save(argv[2 + options], &nfcforum_tag4_data) < 0) {
418 printf(
"Can't save NDEF file '%s'", argv[2 + options]);
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Provide a small API to ease emulation in libnfc.
NFC emulation state machine structure.
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
int nfc_abort_command(nfc_device *pnd)
Abort current running command.
int nfc_emulate_target(nfc_device *pnd, struct nfc_emulator *emulator, const int timeout)
Emulate a target.
#define ERR(...)
Print a error message.
void nfc_close(nfc_device *pnd)
Close from a NFC device.
NFC library context Struct which contains internal options, references, pointers, etc...
Provide some examples shared functions like print, parity calculation, options parsing.