int write_encrypted_tag_key (MifareTag tag, keyvault_t *kv, RSA *global_public, RSA *shop_public, RSA *shop_private, size_t len) { int res = 0; uint8_t *crypted = malloc (RSA_size(global_public)); res = RSA_public_encrypt (len, (unsigned char*) kv->k, (unsigned char*) crypted, global_public, RSA_PKCS1_PADDING); if (res < 0) fprintf (stderr, "Something went wrong while ciphering\n"); printf ("Encrypted key has length %d\n", RSA_size(global_public)); unsigned int siglen = RSA_size (shop_private); unsigned int digestlen = RSA_size(global_public); unsigned char *digest = digest_message (crypted, &digestlen); uint8_t *signature = malloc (siglen); res = RSA_sign (NID_sha1, digest, digestlen, (unsigned char *) signature, &siglen , shop_private); if (res <= 0) fprintf (stderr, "Something went wrong while signing\n"); res = RSA_verify (NID_sha1, (unsigned char*) digest, digestlen, (unsigned char *) signature, siglen, shop_public); if (res <= 0) fprintf (stderr, "Something went wrong while signing, can't verify the thing with our pubkey\n"); MifareDESFireAID aid = mifare_desfire_aid_new (0x1); res = mifare_desfire_select_application(tag, aid); if (res < 0) errx (EXIT_FAILURE, "Application selection failed"); free (aid); MifareDESFireKey key = mifare_desfire_3des_key_new_with_version (kv->k_w_1); mifare_desfire_key_set_version (key, 0x01); res = mifare_desfire_authenticate (tag, 1, key); if (res < 0) freefare_perror(tag, "Authentication to application #1 failed"); mifare_desfire_key_free (key); ssize_t written = mifare_desfire_write_data (tag, 0x01, 0x0, 0x80, crypted); if (written < 0) freefare_perror(tag, "Writing data to tag"); else printf ("Wrote %ld bytes E(K) to card ...\n", written); written = mifare_desfire_write_data (tag, 0x02, 0x0, 0x80, signature); if (written < 0) freefare_perror(tag, "Writing data to tag"); else printf ("Wrote %ld bytes Sign(E(K)) to card ...\n", written); free (crypted); free (signature); free (digest); return res; }
int explain_tag (MifareTag tag) { bool aborting = false; mifare_desfire_connect (tag); MifareDESFireAID ucard_info_aid = mifare_desfire_aid_new (UCARD_INFO_AID); if (mifare_desfire_select_application (tag, ucard_info_aid) < 0) { freefare_perror (tag, "mifare_desfire_select_application"); return -1; } free (ucard_info_aid); MifareDESFireKey key = mifare_desfire_aes_key_new (admin_key_data); if (mifare_desfire_authenticate_aes (tag, 0, key) < 0) { freefare_perror (tag, "mifare_desfire_authenticate_aes"); return -1; } uint8_t records[(3+16)*32]; int records_length; records_length = mifare_desfire_read_records_ex (tag, USER_KEYRING_FILENO, 0, 0, records, USER_KEYRING_COMMUNICATION_MODE); if (records_length < 0) { if (BOUNDARY_ERROR == mifare_desfire_last_picc_error (tag)) { warnx ("Card is empty"); return 0; } freefare_perror (tag, "mifare_desfire_read_records_ex"); return -1; } for (int i = 0; (!aborting) && (i < records_length); i += (3+16)) { uint32_t raw_aid = records[i] << 16 | records[i+1] << 8 | records[i+2]; MifareDESFireAID aid = mifare_desfire_aid_new (raw_aid); MifareDESFireKey key = mifare_desfire_des_key_new (records + i + 3); if (explain_application (tag, aid, key) < 0) aborting = true; mifare_desfire_key_free (key); free (aid); } mifare_desfire_disconnect (tag); return (aborting) ? -1 : 0; }
int explain_application (MifareTag tag, MifareDESFireAID aid, MifareDESFireKey key) { char buffer[1024]; if (mifare_desfire_select_application (tag, aid) < 0) { fprintf (stderr, "mifare_desfire_select_application() failed\n"); return -1; } if (mifare_desfire_authenticate (tag, USER_ACCESS_KEYNO, key) < 0) { freefare_perror (tag, "mifare_desfire_authenticate_des"); return -1; } ssize_t len = mifare_desfire_read_data_ex (tag, UCARD_METDATA_FILENO, 0, 0, buffer, USER_ACCESS_COMMUNICATION_MODE); if (len < 0) { fprintf (stderr, "mifare_desfire_read_data_ex() failed\n"); return -1; } char *p = buffer; fprintf (stdout, " Application \"%s\" with AID 0x%06x has the following files:\n", p, mifare_desfire_aid_get_aid (aid)); p = strchr (p, '\0'); p++; int file_no = 0; while (*p) { fprintf (stdout, " File %2d - %s\n", file_no++, p); p = strchr (p, '\0'); p++; if (UCARD_METDATA_FILENO == file_no) file_no++; } return 0; }
int main(int argc, char *argv[]) { int ch; int error = EXIT_SUCCESS; nfc_device *device = NULL; MifareTag *tags = NULL; while ((ch = getopt (argc, argv, "hyK:")) != -1) { switch (ch) { case 'h': usage(argv[0]); exit (EXIT_SUCCESS); break; case 'y': configure_options.interactive = false; break; case 'K': if (strlen(optarg) != 16) { usage(argv[0]); exit (EXIT_FAILURE); } uint64_t n = strtoull(optarg, NULL, 16); int i; for (i=7; i>=0; i--) { key_data_picc[i] = (uint8_t) n; n >>= 8; } break; default: usage(argv[0]); exit (EXIT_FAILURE); } } // Remaining args, if any, are in argv[optind .. (argc-1)] nfc_connstring devices[8]; size_t device_count; nfc_context *context; nfc_init (&context); if (context == NULL) errx(EXIT_FAILURE, "Unable to init libnfc (malloc)"); device_count = nfc_list_devices (context, devices, 8); if (device_count <= 0) errx (EXIT_FAILURE, "No NFC device found."); for (size_t d = 0; (!error) && (d < device_count); d++) { device = nfc_open (context, devices[d]); if (!device) { warnx ("nfc_open() failed."); error = EXIT_FAILURE; continue; } tags = freefare_get_tags (device); if (!tags) { nfc_close (device); errx (EXIT_FAILURE, "Error listing Mifare DESFire tags."); } for (int i = 0; (!error) && tags[i]; i++) { if (DESFIRE != freefare_get_tag_type (tags[i])) continue; char *tag_uid = freefare_get_tag_uid (tags[i]); char buffer[BUFSIZ]; int res; res = mifare_desfire_connect (tags[i]); if (res < 0) { warnx ("Can't connect to Mifare DESFire target."); error = EXIT_FAILURE; break; } // Make sure we've at least an EV1 version struct mifare_desfire_version_info info; res = mifare_desfire_get_version (tags[i], &info); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_get_version"); error = 1; break; } if (info.software.version_major < 1) { warnx ("Found old DESFire, skipping"); continue; } printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid); bool do_it = true; if (configure_options.interactive) { printf ("Change ATS? [yN] "); fgets (buffer, BUFSIZ, stdin); do_it = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } else { printf ("\n"); } if (do_it) { MifareDESFireKey key_picc = mifare_desfire_des_key_new_with_version (key_data_picc); res = mifare_desfire_authenticate (tags[i], 0, key_picc); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_authenticate"); error = EXIT_FAILURE; break; } mifare_desfire_key_free (key_picc); res = mifare_desfire_set_ats (tags[i], new_ats); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_set_ats"); error = EXIT_FAILURE; break; } } mifare_desfire_disconnect (tags[i]); free (tag_uid); } freefare_free_tags (tags); nfc_close (device); } nfc_exit (context); exit (error); } /* main() */
int main (void) { uint8_t issuer_key_data[16]; nfc_connstring nfc_devices[8]; size_t nfc_device_count; nfc_device_count = nfc_list_devices (NULL, nfc_devices, 8); for (size_t n = 0; n < nfc_device_count; n++) { nfc_device *nfc_device = nfc_open (NULL, nfc_devices[n]); MifareTag *tags = freefare_get_tags (nfc_device); for (int i = 0; tags[i]; i++) { MifareTag tag = tags[i]; if (DESFIRE == freefare_get_tag_type (tag)) { printf ("Fond Mifare DESFire with UID: %s\n", freefare_get_tag_uid (tag)); printf ("Issuer private key: "); char buffer[BUFSIZ]; system ("stty -echo"); fgets (buffer, BUFSIZ, stdin); system ("stty echo"); char *p; if ((p = strchr (buffer, '\n'))) *p = '\0'; ucard_derivate_password (buffer, strlen (buffer), 16, issuer_key_data); memset (buffer, '\0', strlen (buffer)); MifareDESFireKey key = mifare_desfire_aes_key_new (issuer_key_data); MifareDESFireAID ucard_info_aid = mifare_desfire_aid_new (UCARD_INFO_AID); int res = mifare_desfire_connect (tag); res = mifare_desfire_select_application (tag, ucard_info_aid); if (res < 0) { freefare_perror (tag, "mifare_desfire_select_application"); goto end; } res = mifare_desfire_authenticate_aes (tag, 1, key); if (res < 0) { freefare_perror (tag, "mifare_desfire_authenticate_aes"); goto end; } char owner_info[BUFSIZ]; res = mifare_desfire_read_data_ex (tag, 10, 0, 0, owner_info, MDCM_ENCIPHERED); if (res < 0) { freefare_perror (tag, "mifare_desfire_read_data"); goto end; } owner_info[res] = '\0'; printf ("Owner: %s\n", owner_info); end: mifare_desfire_disconnect (tag); mifare_desfire_key_free (key); free (ucard_info_aid); } } nfc_close (nfc_device); } exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int ch; int error = EXIT_SUCCESS; nfc_device *device = NULL; FreefareTag *tags = NULL; while ((ch = getopt (argc, argv, "hy")) != -1) { switch (ch) { case 'h': usage(argv[0]); exit (EXIT_SUCCESS); break; case 'y': configure_options.interactive = false; break; default: usage(argv[0]); exit (EXIT_FAILURE); } } // Remaining args, if any, are in argv[optind .. (argc-1)] nfc_connstring devices[8]; size_t device_count; nfc_context *context; nfc_init (&context); if (context == NULL) errx(EXIT_FAILURE, "Unable to init libnfc (malloc)"); device_count = nfc_list_devices (context, devices, 8); if (device_count <= 0) errx (EXIT_FAILURE, "No NFC device found."); for (size_t d = 0; (!error) && (d < device_count); d++) { device = nfc_open (context, devices[d]); if (!device) { warnx ("nfc_open() failed."); error = EXIT_FAILURE; continue; } tags = freefare_get_tags (device); if (!tags) { nfc_close (device); errx (EXIT_FAILURE, "Error listing Mifare DESFire tags."); } for (int i = 0; (!error) && tags[i]; i++) { if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i])) continue; char *tag_uid = freefare_get_tag_uid (tags[i]); char buffer[BUFSIZ]; int res; res = mifare_desfire_connect (tags[i]); if (res < 0) { warnx ("Can't connect to Mifare DESFire target."); error = EXIT_FAILURE; break; } // Make sure we've at least an EV1 version struct mifare_desfire_version_info info; res = mifare_desfire_get_version (tags[i], &info); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_get_version"); error = 1; break; } if (info.software.version_major < 1) { warnx ("Found old DESFire, skipping"); continue; } printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid); bool do_it = true; if (configure_options.interactive) { printf ("Change default key? [yN] "); fgets (buffer, BUFSIZ, stdin); do_it = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } else { printf ("\n"); } if (do_it) { MifareDESFireKey default_key = mifare_desfire_des_key_new_with_version (null_key_data); res = mifare_desfire_authenticate (tags[i], 0, default_key); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_authenticate"); error = EXIT_FAILURE; break; } mifare_desfire_key_free (default_key); MifareDESFireKey new_key = mifare_desfire_des_key_new (new_key_data); mifare_desfire_key_set_version (new_key, NEW_KEY_VERSION); res = mifare_desfire_set_default_key (tags[i], new_key); free (new_key); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_set_default_key"); error = EXIT_FAILURE; break; } /* * Perform some tests to ensure the function actually worked * (it's hard to create a unit-test to do so). */ MifareDESFireAID aid = mifare_desfire_aid_new (0x112233); res = mifare_desfire_create_application (tags[i], aid, 0xFF, 1); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_create_application"); error = EXIT_FAILURE; break; } res = mifare_desfire_select_application (tags[i], aid); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_select_application"); error = EXIT_FAILURE; break; } uint8_t version; res = mifare_desfire_get_key_version (tags[i], 0, &version); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_get_key_version"); error = EXIT_FAILURE; break; } if (version != NEW_KEY_VERSION) { fprintf (stderr, "Wrong key version: %02x (expected %02x).\n", version, NEW_KEY_VERSION); error = EXIT_FAILURE; /* continue */ } new_key = mifare_desfire_des_key_new (new_key_data); res = mifare_desfire_authenticate (tags[i], 0, new_key); free (new_key); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_authenticate"); error = EXIT_FAILURE; break; } free (aid); /* Resetdefault settings */ res = mifare_desfire_select_application (tags[i], NULL); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_select_application"); error = EXIT_FAILURE; break; } default_key = mifare_desfire_des_key_new (null_key_data); res = mifare_desfire_authenticate (tags[i], 0, default_key); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_authenticate"); error = EXIT_FAILURE; break; } res = mifare_desfire_set_default_key (tags[i], default_key); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_set_default_key"); error = EXIT_FAILURE; break; } mifare_desfire_key_free (default_key); /* Wipeout the card */ res = mifare_desfire_format_picc (tags[i]); if (res < 0) { freefare_perror (tags[i], "mifare_desfire_format_picc"); error = EXIT_FAILURE; break; } } mifare_desfire_disconnect (tags[i]); free (tag_uid); } freefare_free_tags (tags); nfc_close (device); } nfc_exit (context); exit (error); }
int setup_keys (MifareTag tag, keyvault_t *kv) { int res = 0; MifareDESFireAID aid = mifare_desfire_aid_new (0x1); res = mifare_desfire_select_application(tag, aid); if (res < 0) errx (EXIT_FAILURE, "Application selection failed"); free (aid); MifareDESFireKey old_key = mifare_desfire_des_key_new_with_version (initial_key); res = mifare_desfire_authenticate (tag, 0, old_key); if (res < 0) errx (EXIT_FAILURE, "Authentication to application 1 failed"); MifareDESFireKey new_key; if (get_keytype_3DES (kv, CRYPTO_KEY_KM1)) { printf ("Setting 3DES key K_M1 ...\n"); new_key = mifare_desfire_3des_key_new_with_version (kv->k_m_1); } else { printf ("Setting DES key K_M1 ...\n"); new_key = mifare_desfire_des_key_new_with_version (kv->k_m_1); } res = mifare_desfire_change_key (tag, 0x00, new_key, old_key); if (res < 0) freefare_perror (tag, "Change key 0x00"); res = mifare_desfire_authenticate (tag, 0, new_key); if (res < 0) freefare_perror (tag, "Reauthing after changing key 0x00"); mifare_desfire_key_free (new_key); if (get_keytype_3DES (kv, CRYPTO_KEY_KW1)) { printf ("Setting 3DES key K_W1 ...\n"); new_key = mifare_desfire_3des_key_new_with_version (kv->k_w_1); } else { printf ("Setting DES key K_W1 ...\n"); new_key = mifare_desfire_des_key_new_with_version (kv->k_w_1); } res = mifare_desfire_change_key (tag, 0x01, new_key, old_key); if (res < 0) freefare_perror (tag, "Change key 0x01"); mifare_desfire_key_free (new_key); /* AID 2 ... */ aid = mifare_desfire_aid_new (0x2); res = mifare_desfire_select_application(tag, aid); if (res < 0) errx (EXIT_FAILURE, "Application selection failed"); free (aid); res = mifare_desfire_authenticate (tag, 0, old_key); if (res < 0) errx (EXIT_FAILURE, "Authentication to application 2 failed"); if (get_keytype_3DES (kv, CRYPTO_KEY_KM2)) { printf ("Setting 3DES key K_M2 ...\n"); new_key = mifare_desfire_3des_key_new_with_version (kv->k_m_2); } else { printf ("Setting DES key K_M2 ...\n"); new_key = mifare_desfire_des_key_new_with_version (kv->k_m_2); } res = mifare_desfire_change_key (tag, 0x00, new_key, old_key); if (res < 0) freefare_perror (tag, "Change key 0x00"); res = mifare_desfire_authenticate (tag, 0, new_key); if (res < 0) freefare_perror (tag, "Reauthing after changing key 0x00"); mifare_desfire_key_free (new_key); if (get_keytype_3DES (kv, CRYPTO_KEY_K)) { printf ("Setting 3DES key K ...\n"); new_key = mifare_desfire_3des_key_new_with_version (kv->k); } else { printf ("Setting DES key K ...\n"); new_key = mifare_desfire_des_key_new_with_version (kv->k); } res = mifare_desfire_change_key (tag, 0x01, new_key, old_key); if (res < 0) freefare_perror (tag, "Change key 0x01"); mifare_desfire_key_free (new_key); mifare_desfire_key_free (old_key); return EXIT_SUCCESS; }