#include #include #include #include #include #include #include #include "poll_desfire.h" #define AID 0x22eaa0 #define RANDOM_UID_SIZE 8 void init_keys(MifareDESFireKey *null_key, MifareDESFireKey *master_key, char const *name) { uint8_t const key_data_null[8] = {0, 0, 0, 0, 0, 0, 0, 0}; *null_key = mifare_desfire_des_key_new_with_version(key_data_null); uint8_t key_data_real[16] = {0}; { FILE *f = fopen(name, "rb"); if (!f) { errx(EXIT_FAILURE, "error opening key file: %s", name); } if (fread(key_data_real, 1, sizeof key_data_real, f) < sizeof key_data_real) { errx(EXIT_FAILURE, "key file too small."); } fclose(f); } *master_key = mifare_desfire_aes_key_new(key_data_real); } int main(int argc, char **argv) { int error = EXIT_SUCCESS; nfc_context *context = NULL; nfc_device *device = NULL; FreefareTag *tags = NULL; MifareDESFireKey key_null, key_master; MifareDESFireAID aid = mifare_desfire_aid_new(AID); error = init(&context, &device); init_keys(&key_null, &key_master, (argc > 1) ? argv[1] : "key"); FILE *out = argc > 2 ? fopen(argv[2], "w") : stdout; while (true) { tags = freefare_get_tags(device); if (!tags) { nfc_close(device); errx(EXIT_FAILURE, "Error listing tags."); } for (int id = 0; tags[id]; id++) { FreefareTag tag = tags[id]; if (MIFARE_DESFIRE != freefare_get_tag_type(tag)) continue; char *tag_uid = freefare_get_tag_uid(tag); /* Result of various operations */ int res; res = mifare_desfire_connect(tag); if (res < 0) { warnx("Can't connect to Mifare DESFire target."); goto next_tag; } if (mifare_desfire_select_application(tag, aid) != 0) { // Check for old card with our key as master key res = mifare_desfire_authenticate(tag, 0, key_master); if (res >= 0) { warnx("Old tag detected: %s", tag_uid); res = mifare_desfire_change_key(tag, 0, key_null, key_master); if (res < 0) { warnx("Could not change key: %d", res); goto next_tag; } } // Card needs to have default null key as master res = mifare_desfire_authenticate(tag, 0, key_null); if (res < 0) { warnx("Could not authenticate: %d", res); goto next_tag; } // create application res = mifare_desfire_create_application_aes( tag, aid, MDAPP_SETTINGS(0, 1, 0, 0, 1), 1); if (res < 0) { warnx("Could not create application: %d", res); goto next_tag; } // Select it res = mifare_desfire_select_application(tag, aid); if (res < 0) { warnx("Application not selectable after creation: %d", res); goto next_tag; } // Key should be null res = mifare_desfire_authenticate_aes(tag, 0, key_null); if (res < 0) { warnx( "Could not authenticate new application with default " "key: %d", res); goto next_tag; } // Update to our key res = mifare_desfire_change_key(tag, 0, key_master, key_null); if (res < 0) { warnx( "Could not change key of new application to master " "key: %d", res); goto next_tag; } // Authenticate with new key res = mifare_desfire_authenticate_aes(tag, 0, key_master); if (res < 0) { warnx( "Could not authenticate new application with our key: " "%d", res); goto next_tag; } // Create file res = mifare_desfire_create_std_data_file( tag, 0, 0, MDAR(0, 0, 0, 0), RANDOM_UID_SIZE); if (res < 0) { warnx("Could not create data file: %d", res); goto next_tag; } // Grab random data for it unsigned char uid_data[RANDOM_UID_SIZE]; { int fd = open("/dev/urandom", O_RDONLY); if (fd < 0) { warnx("Could not open /dev/urandom"); goto next_tag; } if (RANDOM_UID_SIZE != read(fd, &uid_data[0], RANDOM_UID_SIZE)) { warnx("Could not read data from /dev/random"); goto next_tag; } close(fd); } // Write data res = mifare_desfire_write_data(tag, 0, 0, RANDOM_UID_SIZE, &uid_data[0]); if (res < 0) { warnx("Could not write UID data to tag: %d", res); goto next_tag; } } // Authenticate with our key res = mifare_desfire_authenticate_aes(tag, 0, key_master); if (res < 0) { warnx("Authentication on application failed: %d", res); goto next_tag; } // Grab UID uint8_t data[RANDOM_UID_SIZE]; res = mifare_desfire_read_data(tag, 0, 0, RANDOM_UID_SIZE, &data[0]); if (res != RANDOM_UID_SIZE) { warnx("Could not read all bytes from tag: %d", res); goto next_tag; } // Print out key ID and UID fprintf(out, "%s:", tag_uid); for (int j = 0; j < RANDOM_UID_SIZE; j++) { fprintf(out, "%02x", data[j]); } fprintf(out, "\n"); fflush(out); next_tag: free(tag_uid); mifare_desfire_disconnect(tag); } while (freefare_selected_tag_is_present(device)) ; freefare_free_tags(tags); fflush(stdout); fflush(stderr); } mifare_desfire_key_free(key_null); mifare_desfire_key_free(key_master); nfc_close(device); nfc_exit(context); exit(error); }