int fix_mad_trailer_block (nfc_device_t *device, MifareTag tag, MifareClassicSectorNumber sector, MifareClassicKey key, MifareClassicKeyType key_type) { MifareClassicBlock block; mifare_classic_trailer_block (&block, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, 0x00, default_keyb); if (mifare_classic_authenticate (tag, mifare_classic_sector_last_block (sector), key, key_type) < 0) { nfc_perror (device, "fix_mad_trailer_block mifare_classic_authenticate"); return -1; } if (mifare_classic_write (tag, mifare_classic_sector_last_block (sector), block) < 0) { nfc_perror (device, "mifare_classic_write"); return -1; } return 0; }
void test_mifare_classic_sector_boundaries (void) { for (int i=0; i < 32; i++) { for (int j=0; j < 4; j++) { cut_assert_equal_int (4 * i, mifare_classic_sector_first_block (mifare_classic_block_sector (4 * i)), cut_message ("Wrong first block number for block %d", i)); cut_assert_equal_int (4 * i + 3, mifare_classic_sector_last_block (mifare_classic_block_sector (4 * i + j)), cut_message ("Wrong last block number for block %d", i)); } } for (int i=0; i < 8; i++) { for (int j=0; j < 16; j++) { cut_assert_equal_int (128 + 16 * i, mifare_classic_sector_first_block (mifare_classic_block_sector (128 + 16 * i)), cut_message ("Wrong last block number for block %d", i)); cut_assert_equal_int (128 + 16 * i + 15, mifare_classic_sector_last_block (mifare_classic_block_sector (128 + 16 * i + j)), cut_message ("Wrong last block number for block %d", i)); } } }
ssize_t mifare_application_write (MifareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type) { ssize_t res = 0; MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid); MifareClassicSectorNumber *s = sectors; if (!sectors) return errno = EBADF, -1; while (*s && nbytes && (res >= 0)) { MifareClassicBlockNumber first_block = mifare_classic_sector_first_block (*s); MifareClassicBlockNumber last_block = mifare_classic_sector_last_block (*s); MifareClassicBlockNumber b = first_block; MifareClassicBlock block; if (mifare_classic_authenticate (tag, first_block, key, key_type) < 0) { res = -1; break; } while ((b < last_block) && nbytes) { size_t n = MIN (nbytes, 16); // Avoid overwriting existing data with uninitialized memory. if (n < 16) { if (mifare_classic_read (tag, b, &block) < 0) { res = -1; break; } } memcpy (&block, (uint8_t *)buf + res, n); if (mifare_classic_write (tag, b, block) < 0) { res = -1; break; } nbytes -= n; res += n; b++; } s++; } free (sectors); return res; }
int try_format_sector (MifareTag tag, MifareClassicSectorNumber sector) { display_progress (); size_t i; for (i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++) { MifareClassicBlockNumber block = mifare_classic_sector_last_block (sector); if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_A))) { if (0 == mifare_classic_format_sector (tag, sector)) { mifare_classic_disconnect (tag); return 1; } else if (EIO == errno) { err (EXIT_FAILURE, "sector %d", sector); } mifare_classic_disconnect (tag); } if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_B))) { if (0 == mifare_classic_format_sector (tag, sector)) { mifare_classic_disconnect (tag); return 1; } else if (EIO == errno) { err (EXIT_FAILURE, "sector %d", sector); } mifare_classic_disconnect (tag); } } sprintf(message_erreur,"No known authentication key for sector %d !", sector); return 0; }
int search_sector_key (MifareTag tag, MifareClassicSectorNumber sector, MifareClassicKey *key, MifareClassicKeyType *key_type) { MifareClassicBlockNumber block = mifare_classic_sector_last_block (sector); /* * FIXME: We should not assume that if we have full access to trailer block * we also have a full access to data blocks. */ mifare_classic_disconnect (tag); for (size_t i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++) { if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_A))) { if ((1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYA, MFC_KEY_A)) && (1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A)) && (1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYB, MFC_KEY_A))) { memcpy (key, &default_keys[i], sizeof (MifareClassicKey)); *key_type = MFC_KEY_A; return 1; } } mifare_classic_disconnect (tag); if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_B))) { if ((1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYA, MFC_KEY_B)) && (1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B)) && (1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYB, MFC_KEY_B))) { memcpy (key, &default_keys[i], sizeof (MifareClassicKey)); *key_type = MFC_KEY_B; return 1; } } mifare_classic_disconnect (tag); } warnx ("No known authentication key for sector 0x%02x\n", sector); return 0; }
int main(int argc, const char *argv[]) { nfc_device *pnd; //nfc_target nt; MifareTag *tags = NULL; int i,j,k; int nbrsect=0; MifareClassicBlock data; // Allocate only a pointer to nfc_context nfc_context *context; // Initialize libnfc and set the nfc_context nfc_init(&context); if (context == NULL) { printf("Unable to init libnfc\n"); exit(EXIT_FAILURE); } // Open, using the first available NFC device which can be in order of selection: // - default device specified using environment variable or // - first specified device in libnfc.conf (/etc/nfc) or // - first specified device in device-configuration directory (/etc/nfc/devices.d) or // - first auto-detected (if feature is not disabled in libnfc.conf) device pnd = nfc_open(context, NULL); if (pnd == NULL) { printf("ERROR: %s\n", "Unable to open NFC device."); exit(EXIT_FAILURE); } printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); tags = freefare_get_tags(pnd); if (!tags) { printf("no Mifare classic\n"); } else { for (i = 0; tags[i]; i++) { switch(freefare_get_tag_type(tags[i])) { case CLASSIC_1K: printf("%u : Mifare 1k (S50) : %s\n", i, freefare_get_tag_uid(tags[i])); nbrsect=16; break; case CLASSIC_4K: printf("%u : Mifare 4k (S70) : %s\n", i, freefare_get_tag_uid(tags[i])); nbrsect=40; break; default: printf("%u : other ISO14443A tag : %s\n", i, freefare_get_tag_uid(tags[i])); } } } if (!tags[0]) { printf("no tag found !\n"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } printf ("Found %s\n", freefare_get_tag_friendly_name (tags[0])); /* MifareClassicBlockNumber dablock = 1; if(mifare_classic_connect(tags[0]) == OPERATION_OK) { printf("Connected !\n"); if(mifare_classic_authenticate(tags[0], dablock, keys[0], MFC_KEY_A) == OPERATION_OK) { printf("Authenticated !\n"); if(mifare_classic_get_data_block_permission (tags[0], dablock, MCAB_R|MCAB_W, MFC_KEY_A)) printf("i can READ block %d with key A\n", dablock); if(mifare_classic_get_trailer_block_permission (tags[0], ((dablock)/4)*4+3, MCAB_READ_KEYB, MFC_KEY_B)) printf("i can READ KEY A in trailer\n"); } } */ for(i=0; i<nbrsect; i++) { for(j=0; j < sizeof(keys)/sizeof(keys[0]); j++) { if((mifare_classic_connect(tags[0]) == OPERATION_OK) && (mifare_classic_authenticate( tags[0], mifare_classic_sector_last_block(i), keys[j], MFC_KEY_A) == OPERATION_OK)) { printf("sector %02d auth with A[%d]\n", i, j); for(k=mifare_classic_sector_first_block(i); k<=mifare_classic_sector_last_block(i); k++) { if(mifare_classic_read(tags[0], k, &data) == OPERATION_OK) { print_hex(data,16); } else { printf("read error\n"); } } mifare_classic_disconnect(tags[0]); break; } mifare_classic_disconnect(tags[0]); } printf("\n"); } printf("\n"); freefare_free_tags(tags); // Close NFC device nfc_close(pnd); // Release the context nfc_exit(context); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int res; nfc_connstring devices[8]; size_t device_count; nfc_context *nfcctx; char *uid = NULL; init_crypto_state(); nfc_init(&nfcctx); device_count = nfc_list_devices(nfcctx,devices,8); if (device_count <= 0) { std::cerr << "No device found" << std::endl; } device = nfc_open(nfcctx, devices[0]); tags = freefare_get_tags(device); if (tags[0] == NULL) { std::cerr << "No tag on device" << std::endl; exit(1); } for (int i = 0; tags[i]; i++) { if (freefare_get_tag_type(tags[i]) == CLASSIC_1K) { tag = tags[i]; res = mifare_classic_connect(tag); if (res != 0) { std::cout << "Error connecting to MiFare Classic" << std::endl; exit(1); } std::cout << "Connected to MiFare Classic" << std::endl; uid = freefare_get_tag_uid(tag); break; } } std::cout << "UID: " << uid << std::endl; MifareClassicKey *keyA = (MifareClassicKey *)get_random_bytes(6); std::cout << "Key A: "; print_hex(*keyA,6); char *b64KeyA = getBase64String((char *)keyA,6); std::cout << b64KeyA << std::endl; std::cout << "Key B: "; MifareClassicKey *keyB = (MifareClassicKey *)get_random_bytes(6); print_hex(*keyB,6); char *b64KeyB = getBase64String((char *)keyB,6); bool addedToServer = addCard(uid,b64KeyA,b64KeyB); if (!addedToServer) { printf("Not added to server\n"); } // Authenticate with default key to make changes MifareClassicBlockNumber lastTrailer = mifare_classic_sector_last_block(15); res = mifare_classic_authenticate(tag,lastTrailer,defaultKey,MFC_KEY_A); if (res != 0) { printf("Could not authenticate with default key.. card already formatted?\n"); return -1; } MifareClassicBlockNumber firstBlock = mifare_classic_sector_first_block(15); res = mifare_classic_init_value(tag,firstBlock,SECTOR_15_BLOCK_0_INIT,firstBlock); if (res != 0) { printf("Could not init value block %d\n",firstBlock); } MifareClassicBlock trailerBlock; mifare_classic_trailer_block(&trailerBlock,*keyA,0x03,0x00,0x00,0x04,0x00, *keyB); print_hex(trailerBlock, sizeof(MifareClassicBlock)); res = mifare_classic_write(tag,lastTrailer,trailerBlock); if (res != 0) { printf("Could not write sector 15 trailer. STOP\n"); return -1; } MifareClassicBlock normalTrailerBlock; mifare_classic_trailer_block(&normalTrailerBlock,*keyA,0x00,0x00,0x00,0x04,0x00,*keyB); printf("Writing normal trailer block "); print_hex(&normalTrailerBlock[0], sizeof(MifareClassicBlock)); MifareClassicSectorNumber sector; for(sector=0; sector<15;sector++) { MifareClassicBlockNumber trailerBlockNumber = mifare_classic_sector_last_block(sector); res = mifare_classic_authenticate(tag,trailerBlockNumber,defaultKey,MFC_KEY_A); if (res != 0) { printf("Could not authenticate with default key.. card already formatted?\n"); return -1; } res = mifare_classic_write(tag,trailerBlockNumber,normalTrailerBlock); if (res != 0) { printf("Could not write trailer block for sector %d\n",sector); return -1; } else { printf("Wrote trailer block for sector %d\n",sector); } } free(keyA); free(keyB); free(b64KeyA); free(b64KeyB); free(uid); freefare_free_tags(tags); nfc_close(device); }
int main(int argc, char *argv[]) { MYSQL *conn; MYSQL_RES *result; MYSQL_ROW row; int retval; conn = mysql_init(NULL); retval = mysql_real_connect(conn, def_host_name, def_user_name, def_password, def_db_name, def_port_num, def_socket_name, def_client_flag); if(!retval) { printf("Error connecting to database: %s\n", mysql_error(conn)); return -1; } printf("Connection successful\n"); int error = 0; nfc_device_t *device = NULL; MifareTag *tags = NULL; Mad mad; MifareClassicKey transport_key = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; char ndef_input[15] = {'\0'}; char ID[9] = {'\0'}; double balance = 0; printf("\nID: "); scanf("%s", ID); while (getchar() != '\n') continue; printf("\nBalance: "); scanf("%lf", &balance); while (getchar() != '\n') continue; ID[0] = toupper(ID[0]); ID[1] = toupper(ID[1]); char balance_char[6] = {'\0'}; snprintf(balance_char, 6, "%.2f", balance); //ensure balance always with 4 digit, 4.00 => 04.00 char final_balance[6] = {'\0'}; if(strlen(balance_char) != 5) { strcat(final_balance, "0"); strcat(final_balance, balance_char); } else { strcpy(final_balance, balance_char); } strcat(ndef_input, ID); strcat(ndef_input, final_balance); int i = 0; if (ndef_input == NULL) { printf("Write default message.\n"); for(i=0; i < sizeof(ndef_default_msg); i++) { ndef_msg[i] = (uint8_t)ndef_default_msg[i]; } ndef_msg_len = sizeof(ndef_default_msg); } else { for(i=0; i < strlen(ndef_input); i++) { ndef_msg[i] = (uint8_t)ndef_input[i]; } ndef_msg_len = strlen(ndef_input); } printf ("NDEF message is %zu bytes long.\n", ndef_msg_len); struct mifare_classic_key_and_type *card_write_keys; if (!(card_write_keys = malloc (40 * sizeof (*card_write_keys)))) { err (EXIT_FAILURE, "malloc"); } nfc_device_desc_t devices[8]; size_t device_count; nfc_list_devices (devices, 8, &device_count); if (!device_count) errx (EXIT_FAILURE, "No NFC device found."); for (size_t d = 0; d < device_count; d++) { device = nfc_connect (&(devices[d])); if (!device) { warnx ("nfc_connect() failed."); error = EXIT_FAILURE; continue; } tags = freefare_get_tags (device); if (!tags) { nfc_disconnect (device); errx (EXIT_FAILURE, "Error listing MIFARE classic tag."); } for (int i = 0; (!error) && tags[i]; i++) { switch (freefare_get_tag_type (tags[i])) { case CLASSIC_1K: case CLASSIC_4K: break; default: continue; } char *tag_uid = freefare_get_tag_uid (tags[i]); char buffer[BUFSIZ]; printf ("Found %s with UID %s.\n", freefare_get_tag_friendly_name (tags[i]), tag_uid); bool write_ndef = true; for (int n = 0; n < 40; n++) { memcpy(card_write_keys[n].key, transport_key, sizeof (transport_key)); card_write_keys[n].type = MFC_KEY_A; } if (write_ndef) { switch (freefare_get_tag_type (tags[i])) { case CLASSIC_4K: if (!search_sector_key (tags[i], 0x10, &(card_write_keys[0x10].key), &(card_write_keys[0x10].type))) { error = 1; goto error; } /* fallthrough */ case CLASSIC_1K: if (!search_sector_key (tags[i], 0x00, &(card_write_keys[0x00].key), &(card_write_keys[0x00].type))) { error = 1; goto error; } break; default: /* Keep compiler quiet */ break; } if (!error) { /* Ensure the auth key is always a B one. If not, change it! */ switch (freefare_get_tag_type (tags[i])) { case CLASSIC_4K: if (card_write_keys[0x10].type != MFC_KEY_B) { if( 0 != fix_mad_trailer_block (device, tags[i], 0x10, card_write_keys[0x10].key, card_write_keys[0x10].type)) { error = 1; goto error; } memcpy (&(card_write_keys[0x10].key), &default_keyb, sizeof (MifareClassicKey)); card_write_keys[0x10].type = MFC_KEY_B; } /* fallthrough */ case CLASSIC_1K: if (card_write_keys[0x00].type != MFC_KEY_B) { if( 0 != fix_mad_trailer_block (device, tags[i], 0x00, card_write_keys[0x00].key, card_write_keys[0x00].type)) { error = 1; goto error; } memcpy (&(card_write_keys[0x00].key), &default_keyb, sizeof (MifareClassicKey)); card_write_keys[0x00].type = MFC_KEY_B; } break; default: /* Keep compiler quiet */ break; } } size_t encoded_size; uint8_t *tlv_data = tlv_encode (3, ndef_msg, ndef_msg_len, &encoded_size); /* * At his point, we should have collected all information needed to * succeed. */ // If the card already has a MAD, load it. if ((mad = mad_read (tags[i]))) { // If our application already exists, erase it. MifareClassicSectorNumber *sectors, *p; sectors = p = mifare_application_find (mad, mad_nfcforum_aid); if (sectors) { while (*p) { if (mifare_classic_authenticate (tags[i], mifare_classic_sector_last_block(*p), default_keyb, MFC_KEY_B) < 0) { nfc_perror (device, "mifare_classic_authenticate"); error = 1; goto error; } if (mifare_classic_format_sector (tags[i], *p) < 0) { nfc_perror (device, "mifare_classic_format_sector"); error = 1; goto error; } p++; } } free (sectors); mifare_application_free (mad, mad_nfcforum_aid); } else { // Create a MAD and mark unaccessible sectors in the card if (!(mad = mad_new ((freefare_get_tag_type (tags[i]) == CLASSIC_4K) ? 2 : 1))) { perror ("mad_new"); error = 1; goto error; } MifareClassicSectorNumber max_s; switch (freefare_get_tag_type (tags[i])) { case CLASSIC_1K: max_s = 15; break; case CLASSIC_4K: max_s = 39; break; default: /* Keep compiler quiet */ break; } // Mark unusable sectors as so for (size_t s = max_s; s; s--) { if (s == 0x10) continue; if (!search_sector_key (tags[i], s, &(card_write_keys[s].key), &(card_write_keys[s].type))) { mad_set_aid (mad, s, mad_defect_aid); } else if ((memcmp (card_write_keys[s].key, transport_key, sizeof (transport_key)) != 0) && (card_write_keys[s].type != MFC_KEY_A)) { // Revert to transport configuration if (mifare_classic_format_sector (tags[i], s) < 0) { nfc_perror (device, "mifare_classic_format_sector"); error = 1; goto error; } } } } MifareClassicSectorNumber *sectors = mifare_application_alloc (mad, mad_nfcforum_aid, encoded_size); if (!sectors) { nfc_perror (device, "mifare_application_alloc"); error = EXIT_FAILURE; goto error; } if (mad_write (tags[i], mad, card_write_keys[0x00].key, card_write_keys[0x10].key) < 0) { nfc_perror (device, "mad_write"); error = EXIT_FAILURE; goto error; } int s = 0; while (sectors[s]) { MifareClassicBlockNumber block = mifare_classic_sector_last_block (sectors[s]); MifareClassicBlock block_data; mifare_classic_trailer_block (&block_data, mifare_classic_nfcforum_public_key_a, 0x0, 0x0, 0x0, 0x6, 0x40, default_keyb); if (mifare_classic_authenticate (tags[i], block, card_write_keys[sectors[s]].key, card_write_keys[sectors[s]].type) < 0) { nfc_perror (device, "mifare_classic_authenticate"); error = EXIT_FAILURE; goto error; } if (mifare_classic_write (tags[i], block, block_data) < 0) { nfc_perror (device, "mifare_classic_write"); error = EXIT_FAILURE; goto error; } s++; } if ((ssize_t) encoded_size != mifare_application_write (tags[i], mad, mad_nfcforum_aid, tlv_data, encoded_size, default_keyb, MCAB_WRITE_KEYB)) { nfc_perror (device, "mifare_application_write"); error = EXIT_FAILURE; goto error; } //create new student record in database char sql_stmnt[57] = {'\0'}; int n = 0; //filter tag_uid ulong uid_length = strlen(tag_uid); char uid_esc[(2 * uid_length)+1]; mysql_real_escape_string(conn, uid_esc, tag_uid, uid_length); //filter ID ulong id_length = strlen(ID); char id_esc[(2 * id_length)+1]; mysql_real_escape_string(conn, id_esc, ID, id_length); n = snprintf(sql_stmnt, 57, "INSERT INTO student VALUES('%s', '%s', %.1f)", uid_esc, id_esc, balance); retval = mysql_real_query(conn, sql_stmnt, n); if(retval) { printf("Inserting data from DB Failed\n"); return -1; } printf("Insert to DB successful\n"); free (sectors); free (tlv_data); free (mad); } error: free (tag_uid); } //should at the line 412, but the compiler keep on complaining //jump into scope of identifier with variably modified type //no idea why that happens, goto is always call inside any {} to outside error: //even at 412, still not outside enough freefare_free_tags (tags); nfc_disconnect (device); } free (card_write_keys); mysql_free_result(result); mysql_close(conn); exit (error); }