17 Commits

Author SHA1 Message Date
Romuald Conty
fa47ca0223 Releases MFOC 0.10.6 2013-06-06 16:37:48 +02:00
Romuald Conty
9b37ccd725 Restore missing default keys
Bug introduced in previous commit...
2013-04-05 10:15:54 +02:00
Romuald Conty
e5024608f3 Sync nfc-utils.[hc] with devel libnfc files 2013-04-04 23:55:00 +02:00
Romuald Conty
ba7e75cd16 make style 2013-02-20 19:01:41 +01:00
Romuald Conty
0c2d2b5894 Fixes error handling when performing MIFARE commands:
Before this commit, MFOC was considering any errors as authentication error (AUTH command) or permission error (READ/WRITE commands);
With this patch, any error which is not a tag-related error will produce a program exit (with EXIT_FAILURE flag).

Plus, this commit silents MIFARE authentication error while MFOC try some default keys...
2013-02-20 18:50:42 +01:00
Romuald Conty
9a02d34ede Clean GPL licence header in mfoc.c 2013-02-20 18:44:29 +01:00
Romuald Conty
6b65fb4ca2 Cleans code: cosmetic variables alignment 2013-02-20 18:27:16 +01:00
Romuald Conty
0406f0002e Fixes comparaisons between signed and unsigned values 2013-02-20 18:23:07 +01:00
Romuald Conty
b1bc800c83 Removes redundant redeclaration of ‘lfsr_rollback_word’ [-Wredundant-decls] 2013-02-20 18:11:56 +01:00
Romuald Conty
166a1467c2 Use defined macros instead of hardcoded values (MC_AUTH_A/MC_AUTH_B) 2013-02-20 18:08:36 +01:00
Romuald Conty
2b16dc7ff8 Prints symbols signification during key search 2013-02-20 18:05:57 +01:00
Romuald Conty
35489b09a1 Debian: update watch file 2013-02-19 20:05:49 +01:00
Romuald Conty
ab826c9fe8 Debian: upgrade compat from 7 to 9 2013-02-16 15:57:34 +01:00
Romuald Conty
e52c737242 Debian: update program description 2013-02-16 15:56:28 +01:00
Romuald Conty
205050848c Debian: update website and VCS 2013-02-16 15:55:49 +01:00
Romuald Conty
ed16dec250 Debian: allow to use libnfc 1.7.0 RCx 2013-02-16 15:54:23 +01:00
Romuald Conty
d10f2e0bdb Debian: new entry for 0.10.5 2013-02-16 15:50:55 +01:00
13 changed files with 177 additions and 132 deletions

View File

@@ -1,4 +1,4 @@
AC_INIT([mfoc],[0.10.5],[mifare@nethemba.com]) AC_INIT([mfoc],[0.10.6],[mifare@nethemba.com])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])

6
debian/changelog vendored
View File

@@ -1,3 +1,9 @@
mfoc (0.10.5-0) unstable; urgency=low
* New upstream release
-- Romuald Conty <romuald@libnfc.org> Thu, 14 Feb 2013 21:16:42 +0100
mfoc (0.10.4-0) unstable; urgency=low mfoc (0.10.4-0) unstable; urgency=low
* New upstream release * New upstream release

2
debian/compat vendored
View File

@@ -1 +1 @@
7 9

16
debian/control vendored
View File

@@ -2,16 +2,16 @@ Source: mfoc
Section: utils Section: utils
Priority: extra Priority: extra
Maintainer: Thomas Hood <jdthood@gmail.com> Maintainer: Thomas Hood <jdthood@gmail.com>
Build-Depends: debhelper (>= 7.0.50~), dh-autoreconf, libnfc-dev (>= 1.7.0), pkg-config Build-Depends: debhelper (>=9), dh-autoreconf, libnfc-dev (>= 1.7.0~rc1), pkg-config
Standards-Version: 3.9.2 Standards-Version: 3.9.4
Homepage: http://code.google.com/p/nfc-tools/wiki/mfoc Homepage: http://code.google.com/p/mfoc/
Vcs-Svn: http://nfc-tools.googlecode.com/svn/trunk/mfoc Vcs-Git: http://code.google.com/p/mfoc/
Vcs-Browser: http://code.google.com/p/nfc-tools/source/browse/#svn/trunk/mfoc Vcs-Browser: http://code.google.com/p/mfoc/source/browse/
Package: mfoc Package: mfoc
Architecture: any Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends} Depends: ${shlibs:Depends}, ${misc:Depends}
Description: MIFARE Classic offline cracker Description: MIFARE Classic offline cracker
This package includes the mfoc program which cracks the MFOC is an open source implementation of "offline nested" attack. It
encryption keys of the MIFARE Classic chip and dumps the helps to recove keys from MIFARE Classic tags and dump content to a
chip's memory contents to a file. file.

2
debian/rules vendored
View File

@@ -13,4 +13,4 @@ override_dh_installchangelogs:
dh_installchangelogs ChangeLog dh_installchangelogs ChangeLog
%: %:
dh --with autoreconf $@ dh $@ --with autoreconf

2
debian/watch vendored
View File

@@ -3,5 +3,5 @@
# Compulsory line, this is a version 3 file # Compulsory line, this is a version 3 file
version=3 version=3
http://code.google.com/p/nfc-tools/downloads/list .*/mfoc-(.*).tar.gz http://code.google.com/p/mfoc/downloads/list .*/mfoc-(.*).tar.gz

View File

@@ -311,7 +311,6 @@ continue2:
uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb); uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb);
uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb); uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb);
uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb);
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd); uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd);
/** lfsr_rollback_bit /** lfsr_rollback_bit

View File

@@ -1,34 +1,36 @@
/*-
* Mifare Classic Offline Cracker
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contact: <mifare@nethemba.com>
*
* Porting to libnfc 1.3.3: Michal Boska <boska.michal@gmail.com>
* Porting to libnfc 1.3.9 and upper: Romuald Conty <romuald@libnfc.org>
*
*/
/* /*
* This implementation was written based on information provided by the
Mifare Classic Offline Cracker * following documents:
*
Requirements: crapto1 library http://code.google.com/p/crapto1 * http://eprint.iacr.org/2009/137.pdf
libnfc http://www.libnfc.org * http://www.sos.cs.ru.nl/applications/rfid/2008-esorics.pdf
* http://www.cosic.esat.kuleuven.be/rfidsec09/Papers/mifare_courtois_rfidsec09.pdf
This program is free software: you can redistribute it and/or modify * http://www.cs.ru.nl/~petervr/papers/grvw_2009_pickpocket.pdf
it under the terms of the GNU General Public License as published by */
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Contact: <mifare@nethemba.com>
Porting to libnfc 1.3.3: Michal Boska <boska.michal@gmail.com>
Porting to libnfc 1.3.9: Romuald Conty <romuald@libnfc.org>
Porting to libnfc 1.4.x: Romuald Conty <romuald@libnfc.org>
URL http://eprint.iacr.org/2009/137.pdf
URL http://www.sos.cs.ru.nl/applications/rfid/2008-esorics.pdf
URL http://www.cosic.esat.kuleuven.be/rfidsec09/Papers/mifare_courtois_rfidsec09.pdf
URL http://www.cs.ru.nl/~petervr/papers/grvw_2009_pickpocket.pdf
*/
#define _XOPEN_SOURCE 1 // To enable getopt #define _XOPEN_SOURCE 1 // To enable getopt
@@ -249,9 +251,10 @@ int main(int argc, char *const argv[])
t.sectors[s].foundKeyA = t.sectors[s].foundKeyB = false; t.sectors[s].foundKeyA = t.sectors[s].foundKeyB = false;
} }
print_nfc_target(t.nt, true); print_nfc_target(&t.nt, true);
// Try to authenticate to all sectors with default keys fprintf(stdout, "\nTry to authenticate to all sectors with default keys...\n");
fprintf(stdout, "Symbols: '.' no key found, '/' A key found, '\\' B key found, 'x' both keys found\n");
// Set the authentication information (uid) // Set the authentication information (uid)
memcpy(mp.mpa.abtAuthUid, t.nt.nti.nai.abtUid + t.nt.nti.nai.szUidLen - 4, sizeof(mp.mpa.abtAuthUid)); memcpy(mp.mpa.abtAuthUid, t.nt.nti.nai.abtUid + t.nt.nti.nai.szUidLen - 4, sizeof(mp.mpa.abtAuthUid));
// Iterate over all keys (n = number of keys) // Iterate over all keys (n = number of keys)
@@ -274,9 +277,12 @@ int main(int argc, char *const argv[])
if (trailer_block(block)) { if (trailer_block(block)) {
if (!t.sectors[i].foundKeyA) { if (!t.sectors[i].foundKeyA) {
mc = MC_AUTH_A; mc = MC_AUTH_A;
if (!nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) { int res;
// fprintf(stdout, "!!Error: AUTH [Key A:%012llx] sector %02x t_block %02x\n", if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) < 0) {
// bytes_to_num(mp.mpa.abtKey, 6), i, block); if (res != NFC_EMFCAUTHFAIL) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_anticollision(t, r); mf_anticollision(t, r);
} else { } else {
// Save all information about successfull keyA authentization // Save all information about successfull keyA authentization
@@ -286,9 +292,12 @@ int main(int argc, char *const argv[])
} }
if (!t.sectors[i].foundKeyB) { if (!t.sectors[i].foundKeyB) {
mc = MC_AUTH_B; mc = MC_AUTH_B;
if (!nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) { int res;
// fprintf(stdout, "!!Error: AUTH [Key B:%012llx] sector %02x t_block %02x\n", if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) < 0) {
// bytes_to_num(mp.mpa.abtKey, 6), i, block); if (res != NFC_EMFCAUTHFAIL) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_anticollision(t, r); mf_anticollision(t, r);
// No success, try next block // No success, try next block
t.sectors[i].trailer = block; t.sectors[i].trailer = block;
@@ -307,8 +316,6 @@ int main(int argc, char *const argv[])
fprintf(stdout, "."); fprintf(stdout, ".");
} }
fflush(stdout); fflush(stdout);
// fprintf(stdout, "\nSuccess: AUTH [Key %c:%012llx] sector %02x t_block %02x\n",
// (mc == MC_AUTH_A ? 'A' :'B'), bytes_to_num(mp.mpa.abtKey, 6), i, block);
// Save position of a trailer block to sector struct // Save position of a trailer block to sector struct
t.sectors[i++].trailer = block; t.sectors[i++].trailer = block;
} }
@@ -339,10 +346,13 @@ int main(int argc, char *const argv[])
skip = false; skip = false;
for (uint32_t o = 0; o < bk->size; o++) { for (uint32_t o = 0; o < bk->size; o++) {
num_to_bytes(bk->brokenKeys[o], 6, mp.mpa.abtKey); num_to_bytes(bk->brokenKeys[o], 6, mp.mpa.abtKey);
mc = dumpKeysA ? 0x60 : 0x61; mc = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
if (!nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) { int res;
// fprintf(stdout, "!!Error: AUTH [Key A:%012llx] sector %02x t_block %02x, key %d\n", if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) < 0) {
// bytes_to_num(mp.mpa.abtKey, 6), j, t.sectors[j].trailer, o); if (res != NFC_EMFCAUTHFAIL) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_anticollision(t, r); mf_anticollision(t, r);
} else { } else {
// Save all information about successfull authentization // Save all information about successfull authentization
@@ -394,10 +404,13 @@ int main(int argc, char *const argv[])
// fprintf(stdout,"%d %llx\n",ck[i].count, ck[i].key); // fprintf(stdout,"%d %llx\n",ck[i].count, ck[i].key);
// Set required authetication method // Set required authetication method
num_to_bytes(ck[i].key, 6, mp.mpa.abtKey); num_to_bytes(ck[i].key, 6, mp.mpa.abtKey);
mc = dumpKeysA ? 0x60 : 0x61; mc = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
if (!nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) { int res;
// fprintf(stdout, "!!Error: AUTH [Key A:%llx] sector %02x t_block %02x\n", if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) < 0) {
// bytes_to_num(mp.mpa.abtKey, 6), j, t.sectors[j].trailer); if (res != NFC_EMFCAUTHFAIL) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_anticollision(t, r); mf_anticollision(t, r);
} else { } else {
// Save all information about successfull authentization // Save all information about successfull authentization
@@ -454,12 +467,16 @@ int main(int argc, char *const argv[])
// Try A key, auth() + read() // Try A key, auth() + read()
memcpy(mp.mpa.abtKey, t.sectors[i].KeyA, sizeof(t.sectors[i].KeyA)); memcpy(mp.mpa.abtKey, t.sectors[i].KeyA, sizeof(t.sectors[i].KeyA));
if (!nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_A, block, &mp)) { int res;
// ERR ("Error: Auth A"); if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_A, block, &mp)) < 0) {
if (res != NFC_EMFCAUTHFAIL) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_configure(r.pdi); mf_configure(r.pdi);
mf_anticollision(t, r); mf_anticollision(t, r);
} else { // and Read } else { // and Read
if (nfc_initiator_mifare_cmd(r.pdi, MC_READ, block, &mp)) { if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_READ, block, &mp)) >= 0) {
fprintf(stdout, "Block %02d, type %c, key %012llx :", block, 'A', bytes_to_num(t.sectors[i].KeyA, 6)); fprintf(stdout, "Block %02d, type %c, key %012llx :", block, 'A', bytes_to_num(t.sectors[i].KeyA, 6));
print_hex(mp.mpd.abtData, 16); print_hex(mp.mpd.abtData, 16);
mf_configure(r.pdi); mf_configure(r.pdi);
@@ -467,22 +484,32 @@ int main(int argc, char *const argv[])
failure = false; failure = false;
} else { } else {
// Error, now try read() with B key // Error, now try read() with B key
// ERR ("Error: Read A"); if (res != NFC_ERFTRANS) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_configure(r.pdi); mf_configure(r.pdi);
mf_anticollision(t, r); mf_anticollision(t, r);
memcpy(mp.mpa.abtKey, t.sectors[i].KeyB, sizeof(t.sectors[i].KeyB)); memcpy(mp.mpa.abtKey, t.sectors[i].KeyB, sizeof(t.sectors[i].KeyB));
if (!nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_B, block, &mp)) { if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_B, block, &mp)) < 0) {
// ERR ("Error: Auth B"); if (res != NFC_EMFCAUTHFAIL) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_configure(r.pdi); mf_configure(r.pdi);
mf_anticollision(t, r); mf_anticollision(t, r);
} else { // and Read } else { // and Read
if (nfc_initiator_mifare_cmd(r.pdi, MC_READ, block, &mp)) { if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_READ, block, &mp)) >= 0) {
fprintf(stdout, "Block %02d, type %c, key %012llx :", block, 'B', bytes_to_num(t.sectors[i].KeyB, 6)); fprintf(stdout, "Block %02d, type %c, key %012llx :", block, 'B', bytes_to_num(t.sectors[i].KeyB, 6));
print_hex(mp.mpd.abtData, 16); print_hex(mp.mpd.abtData, 16);
mf_configure(r.pdi); mf_configure(r.pdi);
mf_select_tag(r.pdi, &(t.nt)); mf_select_tag(r.pdi, &(t.nt));
failure = false; failure = false;
} else { } else {
if (res != NFC_ERFTRANS) {
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
goto error;
}
mf_configure(r.pdi); mf_configure(r.pdi);
mf_anticollision(t, r); mf_anticollision(t, r);
// ERR ("Error: Read B"); // ERR ("Error: Read B");
@@ -675,10 +702,11 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
uint32_t Nt, NtLast, NtProbe, NtEnc, Ks1; uint32_t Nt, NtLast, NtProbe, NtEnc, Ks1;
int i, m; int i;
uint32_t m;
// Prepare AUTH command // Prepare AUTH command
Auth[0] = (t.sectors[e_sector].foundKeyA) ? 0x60 : 0x61; Auth[0] = (t.sectors[e_sector].foundKeyA) ? MC_AUTH_A : MC_AUTH_B;
iso14443a_crc_append(Auth, 2); iso14443a_crc_append(Auth, 2);
// fprintf(stdout, "\nAuth command:\t"); // fprintf(stdout, "\nAuth command:\t");
// print_hex(Auth, 4); // print_hex(Auth, 4);
@@ -824,7 +852,7 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
// If we are in "Get Recovery" mode // If we are in "Get Recovery" mode
if (mode == 'r') { if (mode == 'r') {
// Again, prepare the Auth command with MC_AUTH_A, recover the block and CRC // Again, prepare the Auth command with MC_AUTH_A, recover the block and CRC
Auth[0] = dumpKeysA ? 0x60 : 0x61; Auth[0] = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
Auth[1] = a_sector; Auth[1] = a_sector;
iso14443a_crc_append(Auth, 2); iso14443a_crc_append(Auth, 2);

View File

@@ -36,36 +36,36 @@ typedef struct {
uint32_t median; uint32_t median;
uint32_t num_distances; uint32_t num_distances;
uint32_t tolerance; uint32_t tolerance;
uint8_t parity[3]; // used for 3 bits of parity information uint8_t parity[3]; // used for 3 bits of parity information
} denonce; // Revealed information about nonce } denonce; // Revealed information about nonce
typedef struct { typedef struct {
nfc_target nt; nfc_target nt;
sector *sectors; // Allocate later, we do not know the number of sectors yet sector *sectors; // Allocate later, we do not know the number of sectors yet
sector e_sector; // Exploit sector sector e_sector; // Exploit sector
uint8_t num_sectors; uint8_t num_sectors;
uint8_t num_blocks; uint8_t num_blocks;
uint32_t authuid; uint32_t authuid;
bool b4K; bool b4K;
} mftag; } mftag;
typedef struct { typedef struct {
uint64_t *possibleKeys; uint64_t *possibleKeys;
uint32_t size; uint32_t size;
} pKeys; } pKeys;
typedef struct { typedef struct {
uint64_t *brokenKeys; uint64_t *brokenKeys;
int32_t size; uint32_t size;
} bKeys; } bKeys;
typedef struct { typedef struct {
nfc_device *pdi; nfc_device *pdi;
} mfreader; } mfreader;
typedef struct { typedef struct {
uint64_t key; uint64_t key;
int count; int count;
} countKeys; } countKeys;

View File

@@ -3,7 +3,7 @@
* *
* Copyright (C) 2009 Roel Verdult * Copyright (C) 2009 Roel Verdult
* Copyright (C) 2010 Romain Tartière * Copyright (C) 2010 Romain Tartière
* Copyright (C) 2010, 2011 Romuald Conty * Copyright (C) 2010, 2011, 2013 Romuald Conty
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -28,10 +28,23 @@
* Note that this license only applies on the examples, NFC library itself is under LGPL * Note that this license only applies on the examples, NFC library itself is under LGPL
* *
*/ */
/** /**
* @file mifare.c * @file mifare.c
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc * @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
*/ */
/*
* This implementation was written based on information provided by the
* following document:
*
* MIFARE Classic Specification
* MF1ICS50
* Functional specification
* Rev. 5.3 - 29 January 2008
* http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf
*/
#include "mifare.h" #include "mifare.h"
#include <string.h> #include <string.h>
@@ -39,25 +52,33 @@
#include <nfc/nfc.h> #include <nfc/nfc.h>
/** /**
* @brief Execute a MIFARE Classic Command * @brief Execute a MIFARE Classic command
* @return Returns true if action was successfully performed; otherwise returns false. * @return Returns NFC_SUCCESS if action was successfully performed; otherwise returns error code (negative value).
* @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
* *
* The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. * The specified MIFARE command will be executed on the tag. There are
* different commands possible, they all require the destination block number.
*
* @note There are three different types of information (Authenticate, Data and Value). * @note There are three different types of information (Authenticate, Data and Value).
* *
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
* They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip).
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write). * After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. *
* Like libnfc's functions, this one returns negative value on error (libnfc's
* error code) but two of them need a special attention in this context (MIFARE
* Classic):
* - NFC_EMFCAUTHFAIL, "MIFARE authentication failed", means key is not valid
* on specified sector.
* - NFC_ERFTRANS, "Invalid received frame", when occurs on MIFARE command
* read or write after a successful authentication, means permissions allowed
* by current acces bytes are not sufficient to process the command.
*/ */
bool int
nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp) nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
{ {
uint8_t abtRx[265]; uint8_t abtRx[265];
size_t szParamLen; size_t szParamLen;
uint8_t abtCmd[265]; uint8_t abtCmd[265];
//bool bEasyFraming;
abtCmd[0] = mc; // The MIFARE Classic command abtCmd[0] = mc; // The MIFARE Classic command
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff) abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
@@ -89,7 +110,7 @@ nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8
// Please fix your code, you never should reach this statement // Please fix your code, you never should reach this statement
default: default:
return false; return NFC_EINVARG;
break; break;
} }
@@ -98,40 +119,23 @@ nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8
memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen); memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen);
// FIXME: Save and restore bEasyFraming // FIXME: Save and restore bEasyFraming
// bEasyFraming = nfc_device_get_property_bool (pnd, NP_EASY_FRAMING, &bEasyFraming); int res;
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) { if ((res = nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) {
nfc_perror(pnd, "nfc_device_set_property_bool"); return res;
return false;
} }
// Fire the mifare command // Fire the mifare command
int res;
if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) { if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
if (res == NFC_ERFTRANS) { return res;
// "Invalid received frame", usual means we are
// authenticated on a sector but the requested MIFARE cmd (read, write)
// is not permitted by current acces bytes;
// So there is nothing to do here.
} else {
nfc_perror(pnd, "nfc_initiator_transceive_bytes");
}
// XXX nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming);
return false;
} }
/* XXX
if (nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming) < 0) {
nfc_perror (pnd, "nfc_device_set_property_bool");
return false;
}
*/
// When we have executed a read command, copy the received bytes into the param // When we have executed a read command, copy the received bytes into the param
if (mc == MC_READ) { if (mc == MC_READ) {
if (res == 16) { if (res == 16) {
memcpy(pmp->mpd.abtData, abtRx, 16); memcpy(pmp->mpd.abtData, abtRx, 16);
} else { } else {
return false; return NFC_EINVARG;
} }
} }
// Command succesfully executed // Command succesfully executed
return true; return NFC_SUCCESS;
} }

View File

@@ -3,7 +3,7 @@
* *
* Copyright (C) 2009 Roel Verdult * Copyright (C) 2009 Roel Verdult
* Copyright (C) 2010 Romain Tartière * Copyright (C) 2010 Romain Tartière
* Copyright (C) 2010, 2011 Romuald Conty * Copyright (C) 2010, 2011, 2013 Romuald Conty
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -35,12 +35,12 @@
*/ */
#ifndef _LIBNFC_MIFARE_H_ #ifndef _LIBNFC_MIFARE_H_
# define _LIBNFC_MIFARE_H_ #define _LIBNFC_MIFARE_H_
# include <nfc/nfc-types.h> #include <nfc/nfc-types.h>
// Compiler directive, set struct alignment to 1 uint8_t for compatibility // Compiler directive, set struct alignment to 1 uint8_t for compatibility
# pragma pack(1) #pragma pack(1)
typedef enum { typedef enum {
MC_AUTH_A = 0x60, MC_AUTH_A = 0x60,
@@ -76,7 +76,7 @@ typedef union {
// Reset struct alignment to default // Reset struct alignment to default
# pragma pack() # pragma pack()
bool nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp); int nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp);
// Compiler directive, set struct alignment to 1 uint8_t for compatibility // Compiler directive, set struct alignment to 1 uint8_t for compatibility
# pragma pack(1) # pragma pack(1)

View File

@@ -1,9 +1,13 @@
/*- /*-
* Public platform independent Near Field Communication (NFC) library examples * Free/Libre Near Field Communication (NFC) library
* *
* Copyright (C) 2009 Roel Verdult * Libnfc historical contributors:
* Copyright (C) 2010, 2011 Romain Tartière * Copyright (C) 2009 Roel Verdult
* Copyright (C) 2009, 2010, 2011, 2012 Romuald Conty * Copyright (C) 2009-2013 Romuald Conty
* Copyright (C) 2010-2012 Romain Tartière
* Copyright (C) 2010-2013 Philippe Teuwen
* Copyright (C) 2012-2013 Ludovic Rousseau
* Additional contributors of this file:
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -115,10 +119,10 @@ print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDat
} }
void void
print_nfc_target(const nfc_target nt, bool verbose) print_nfc_target(const nfc_target *pnt, bool verbose)
{ {
char *s; char *s;
str_nfc_target(&s, nt, verbose); str_nfc_target(&s, pnt, verbose);
printf("%s", s); printf("%s", s);
free(s); nfc_free(s);
} }

View File

@@ -1,9 +1,13 @@
/*- /*-
* Public platform independent Near Field Communication (NFC) library examples * Free/Libre Near Field Communication (NFC) library
* *
* Copyright (C) 2009 Roel Verdult * Libnfc historical contributors:
* Copyright (C) 2010 Romain Tartière * Copyright (C) 2009 Roel Verdult
* Copyright (C) 2010, 2011, 2012 Romuald Conty * Copyright (C) 2009-2013 Romuald Conty
* Copyright (C) 2010-2012 Romain Tartière
* Copyright (C) 2010-2013 Philippe Teuwen
* Copyright (C) 2012-2013 Ludovic Rousseau
* Additional contributors of this file:
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -94,6 +98,6 @@ void print_hex(const uint8_t *pbtData, const size_t szLen);
void print_hex_bits(const uint8_t *pbtData, const size_t szBits); void print_hex_bits(const uint8_t *pbtData, const size_t szBits);
void print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar); void print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar);
void print_nfc_target(const nfc_target nt, bool verbose); void print_nfc_target(const nfc_target *pnt, bool verbose);
#endif #endif