Compare commits
23 Commits
mfoc-0.10.
...
mfoc-0.10.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
290a075956 | ||
|
|
2fa70fb3d3 | ||
|
|
e1a2b0225f | ||
|
|
222ba1838c | ||
|
|
fa47ca0223 | ||
|
|
9b37ccd725 | ||
|
|
e5024608f3 | ||
|
|
ba7e75cd16 | ||
|
|
0c2d2b5894 | ||
|
|
9a02d34ede | ||
|
|
6b65fb4ca2 | ||
|
|
0406f0002e | ||
|
|
b1bc800c83 | ||
|
|
166a1467c2 | ||
|
|
2b16dc7ff8 | ||
|
|
35489b09a1 | ||
|
|
ab826c9fe8 | ||
|
|
e52c737242 | ||
|
|
205050848c | ||
|
|
ed16dec250 | ||
|
|
d10f2e0bdb | ||
|
|
1c5af20e98 | ||
|
|
d65d57d06e |
@@ -1,4 +1,4 @@
|
||||
AC_INIT([mfoc],[0.10.4],[mifare@nethemba.com])
|
||||
AC_INIT([mfoc],[0.10.7],[mifare@nethemba.com])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
@@ -8,7 +8,7 @@ AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/mfoc.c])
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_INIT_AUTOMAKE(dist-bzip2 no-dist-gzip)
|
||||
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
||||
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -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
|
||||
|
||||
* New upstream release
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
7
|
||||
9
|
||||
|
||||
16
debian/control
vendored
16
debian/control
vendored
@@ -2,16 +2,16 @@ Source: mfoc
|
||||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: Thomas Hood <jdthood@gmail.com>
|
||||
Build-Depends: debhelper (>= 7.0.50~), dh-autoreconf, libnfc-dev (>= 1.7.0), pkg-config
|
||||
Standards-Version: 3.9.2
|
||||
Homepage: http://code.google.com/p/nfc-tools/wiki/mfoc
|
||||
Vcs-Svn: http://nfc-tools.googlecode.com/svn/trunk/mfoc
|
||||
Vcs-Browser: http://code.google.com/p/nfc-tools/source/browse/#svn/trunk/mfoc
|
||||
Build-Depends: debhelper (>=9), dh-autoreconf, libnfc-dev (>= 1.7.0~rc1), pkg-config
|
||||
Standards-Version: 3.9.4
|
||||
Homepage: http://code.google.com/p/mfoc/
|
||||
Vcs-Git: http://code.google.com/p/mfoc/
|
||||
Vcs-Browser: http://code.google.com/p/mfoc/source/browse/
|
||||
|
||||
Package: mfoc
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: MIFARE Classic offline cracker
|
||||
This package includes the mfoc program which cracks the
|
||||
encryption keys of the MIFARE Classic chip and dumps the
|
||||
chip's memory contents to a file.
|
||||
MFOC is an open source implementation of "offline nested" attack. It
|
||||
helps to recove keys from MIFARE Classic tags and dump content to a
|
||||
file.
|
||||
|
||||
2
debian/rules
vendored
2
debian/rules
vendored
@@ -13,4 +13,4 @@ override_dh_installchangelogs:
|
||||
dh_installchangelogs ChangeLog
|
||||
|
||||
%:
|
||||
dh --with autoreconf $@
|
||||
dh $@ --with autoreconf
|
||||
|
||||
2
debian/watch
vendored
2
debian/watch
vendored
@@ -3,5 +3,5 @@
|
||||
# Compulsory line, this is a version 3 file
|
||||
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
|
||||
|
||||
|
||||
@@ -311,7 +311,6 @@ continue2:
|
||||
|
||||
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);
|
||||
uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb);
|
||||
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd);
|
||||
|
||||
/** lfsr_rollback_bit
|
||||
|
||||
@@ -62,13 +62,13 @@ extern "C" {
|
||||
x ^= x >> 4;
|
||||
return BIT(0x6996, x & 0xf);
|
||||
#else
|
||||
asm("movl %1, %%eax\n"
|
||||
"mov %%ax, %%cx\n"
|
||||
"shrl $0x10, %%eax\n"
|
||||
"xor %%ax, %%cx\n"
|
||||
"xor %%ch, %%cl\n"
|
||||
"setpo %%al\n"
|
||||
"movzx %%al, %0\n": "=r"(x) : "r"(x): "eax", "ecx");
|
||||
__asm__("movl %1, %%eax\n"
|
||||
"mov %%ax, %%cx\n"
|
||||
"shrl $0x10, %%eax\n"
|
||||
"xor %%ax, %%cx\n"
|
||||
"xor %%ch, %%cl\n"
|
||||
"setpo %%al\n"
|
||||
"movzx %%al, %0\n": "=r"(x) : "r"(x): "eax", "ecx");
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
155
src/mfoc.c
155
src/mfoc.c
@@ -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>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Mifare Classic Offline Cracker
|
||||
|
||||
Requirements: crapto1 library http://code.google.com/p/crapto1
|
||||
libnfc http://www.libnfc.org
|
||||
|
||||
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, 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
|
||||
*/
|
||||
* This implementation was written based on information provided by the
|
||||
* following documents:
|
||||
*
|
||||
* http://eprint.iacr.org/2009/137.pdf
|
||||
* http://www.sos.cs.ru.nl/applications/rfid/2008-esorics.pdf
|
||||
* http://www.cosic.esat.kuleuven.be/rfidsec09/Papers/mifare_courtois_rfidsec09.pdf
|
||||
* http://www.cs.ru.nl/~petervr/papers/grvw_2009_pickpocket.pdf
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 1 // To enable getopt
|
||||
|
||||
@@ -202,10 +204,13 @@ int main(int argc, char *const argv[])
|
||||
for (i=0;!nfc_initiator_select_passive_target(r.pdi, nm, NULL, 0, &t.nt) && i < 10; i++) zsleep (100);
|
||||
*/
|
||||
|
||||
// mf_select_tag(r.pdi, &(t.nt));
|
||||
if (nfc_initiator_select_passive_target(r.pdi, nm, NULL, 0, &t.nt) < 0) {
|
||||
int tag_count;
|
||||
if ((tag_count = nfc_initiator_select_passive_target(r.pdi, nm, NULL, 0, &t.nt)) < 0) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_select_passive_target");
|
||||
goto error;
|
||||
} else if (tag_count == 0) {
|
||||
ERR("No tag found.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Test if a compatible MIFARE tag is used
|
||||
@@ -249,9 +254,10 @@ int main(int argc, char *const argv[])
|
||||
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)
|
||||
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)
|
||||
@@ -274,9 +280,12 @@ int main(int argc, char *const argv[])
|
||||
if (trailer_block(block)) {
|
||||
if (!t.sectors[i].foundKeyA) {
|
||||
mc = MC_AUTH_A;
|
||||
if (!nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) {
|
||||
// fprintf(stdout, "!!Error: AUTH [Key A:%012llx] sector %02x t_block %02x\n",
|
||||
// bytes_to_num(mp.mpa.abtKey, 6), i, block);
|
||||
int res;
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
// Save all information about successfull keyA authentization
|
||||
@@ -286,9 +295,12 @@ int main(int argc, char *const argv[])
|
||||
}
|
||||
if (!t.sectors[i].foundKeyB) {
|
||||
mc = MC_AUTH_B;
|
||||
if (!nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) {
|
||||
// fprintf(stdout, "!!Error: AUTH [Key B:%012llx] sector %02x t_block %02x\n",
|
||||
// bytes_to_num(mp.mpa.abtKey, 6), i, block);
|
||||
int res;
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, block, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
// No success, try next block
|
||||
t.sectors[i].trailer = block;
|
||||
@@ -307,8 +319,6 @@ int main(int argc, char *const argv[])
|
||||
fprintf(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
|
||||
t.sectors[i++].trailer = block;
|
||||
}
|
||||
@@ -339,10 +349,13 @@ int main(int argc, char *const argv[])
|
||||
skip = false;
|
||||
for (uint32_t o = 0; o < bk->size; o++) {
|
||||
num_to_bytes(bk->brokenKeys[o], 6, mp.mpa.abtKey);
|
||||
mc = dumpKeysA ? 0x60 : 0x61;
|
||||
if (!nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) {
|
||||
// fprintf(stdout, "!!Error: AUTH [Key A:%012llx] sector %02x t_block %02x, key %d\n",
|
||||
// bytes_to_num(mp.mpa.abtKey, 6), j, t.sectors[j].trailer, o);
|
||||
mc = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
|
||||
int res;
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
// Save all information about successfull authentization
|
||||
@@ -394,10 +407,13 @@ int main(int argc, char *const argv[])
|
||||
// fprintf(stdout,"%d %llx\n",ck[i].count, ck[i].key);
|
||||
// Set required authetication method
|
||||
num_to_bytes(ck[i].key, 6, mp.mpa.abtKey);
|
||||
mc = dumpKeysA ? 0x60 : 0x61;
|
||||
if (!nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) {
|
||||
// fprintf(stdout, "!!Error: AUTH [Key A:%llx] sector %02x t_block %02x\n",
|
||||
// bytes_to_num(mp.mpa.abtKey, 6), j, t.sectors[j].trailer);
|
||||
mc = dumpKeysA ? MC_AUTH_A : MC_AUTH_B;
|
||||
int res;
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, mc, t.sectors[j].trailer, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_anticollision(t, r);
|
||||
} else {
|
||||
// Save all information about successfull authentization
|
||||
@@ -454,12 +470,16 @@ int main(int argc, char *const argv[])
|
||||
|
||||
// Try A key, auth() + read()
|
||||
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)) {
|
||||
// ERR ("Error: Auth A");
|
||||
int res;
|
||||
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_anticollision(t, r);
|
||||
} 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));
|
||||
print_hex(mp.mpd.abtData, 16);
|
||||
mf_configure(r.pdi);
|
||||
@@ -467,22 +487,32 @@ int main(int argc, char *const argv[])
|
||||
failure = false;
|
||||
} else {
|
||||
// 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_anticollision(t, r);
|
||||
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)) {
|
||||
// ERR ("Error: Auth B");
|
||||
if ((res = nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_B, block, &mp)) < 0) {
|
||||
if (res != NFC_EMFCAUTHFAIL) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
} 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));
|
||||
print_hex(mp.mpd.abtData, 16);
|
||||
mf_configure(r.pdi);
|
||||
mf_select_tag(r.pdi, &(t.nt));
|
||||
failure = false;
|
||||
} else {
|
||||
if (res != NFC_ERFTRANS) {
|
||||
nfc_perror(r.pdi, "nfc_initiator_mifare_cmd");
|
||||
goto error;
|
||||
}
|
||||
mf_configure(r.pdi);
|
||||
mf_anticollision(t, r);
|
||||
// ERR ("Error: Read B");
|
||||
@@ -552,6 +582,10 @@ void mf_init(mfreader *r)
|
||||
{
|
||||
// Connect to the first NFC device
|
||||
nfc_init(&context);
|
||||
if (context == NULL) {
|
||||
ERR("Unable to init libnfc (malloc)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
r->pdi = nfc_open(context, NULL);
|
||||
if (!r->pdi) {
|
||||
printf("No NFC device found.\n");
|
||||
@@ -675,10 +709,11 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
|
||||
|
||||
uint32_t Nt, NtLast, NtProbe, NtEnc, Ks1;
|
||||
|
||||
int i, m;
|
||||
int i;
|
||||
uint32_t m;
|
||||
|
||||
// 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);
|
||||
// fprintf(stdout, "\nAuth command:\t");
|
||||
// print_hex(Auth, 4);
|
||||
@@ -824,7 +859,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 (mode == 'r') {
|
||||
// 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;
|
||||
iso14443a_crc_append(Auth, 2);
|
||||
|
||||
|
||||
24
src/mfoc.h
24
src/mfoc.h
@@ -36,36 +36,36 @@ typedef struct {
|
||||
uint32_t median;
|
||||
uint32_t num_distances;
|
||||
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
|
||||
|
||||
typedef struct {
|
||||
nfc_target nt;
|
||||
nfc_target nt;
|
||||
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_blocks;
|
||||
uint32_t authuid;
|
||||
bool b4K;
|
||||
uint32_t authuid;
|
||||
bool b4K;
|
||||
} mftag;
|
||||
|
||||
typedef struct {
|
||||
uint64_t *possibleKeys;
|
||||
uint32_t size;
|
||||
uint64_t *possibleKeys;
|
||||
uint32_t size;
|
||||
} pKeys;
|
||||
|
||||
typedef struct {
|
||||
uint64_t *brokenKeys;
|
||||
int32_t size;
|
||||
uint64_t *brokenKeys;
|
||||
uint32_t size;
|
||||
} bKeys;
|
||||
|
||||
typedef struct {
|
||||
nfc_device *pdi;
|
||||
nfc_device *pdi;
|
||||
} mfreader;
|
||||
|
||||
typedef struct {
|
||||
uint64_t key;
|
||||
int count;
|
||||
uint64_t key;
|
||||
int count;
|
||||
} countKeys;
|
||||
|
||||
|
||||
|
||||
68
src/mifare.c
68
src/mifare.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2009 Roel Verdult
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mifare.c
|
||||
* @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 <string.h>
|
||||
@@ -39,25 +52,33 @@
|
||||
#include <nfc/nfc.h>
|
||||
|
||||
/**
|
||||
* @brief Execute a MIFARE Classic Command
|
||||
* @return Returns true if action was successfully performed; otherwise returns false.
|
||||
* @brief Execute a MIFARE Classic command
|
||||
* @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.
|
||||
*
|
||||
* 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).
|
||||
*
|
||||
* 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).
|
||||
* 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)
|
||||
{
|
||||
uint8_t abtRx[265];
|
||||
size_t szParamLen;
|
||||
uint8_t abtCmd[265];
|
||||
//bool bEasyFraming;
|
||||
|
||||
abtCmd[0] = mc; // The MIFARE Classic command
|
||||
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
|
||||
default:
|
||||
return false;
|
||||
return NFC_EINVARG;
|
||||
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);
|
||||
|
||||
// FIXME: Save and restore bEasyFraming
|
||||
// bEasyFraming = nfc_device_get_property_bool (pnd, NP_EASY_FRAMING, &bEasyFraming);
|
||||
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
|
||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
||||
return false;
|
||||
int res;
|
||||
if ((res = nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) {
|
||||
return res;
|
||||
}
|
||||
// Fire the mifare command
|
||||
int res;
|
||||
if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
|
||||
if (res == NFC_ERFTRANS) {
|
||||
// "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;
|
||||
return res;
|
||||
}
|
||||
/* 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
|
||||
if (mc == MC_READ) {
|
||||
if (res == 16) {
|
||||
memcpy(pmp->mpd.abtData, abtRx, 16);
|
||||
} else {
|
||||
return false;
|
||||
return NFC_EINVARG;
|
||||
}
|
||||
}
|
||||
// Command succesfully executed
|
||||
return true;
|
||||
return NFC_SUCCESS;
|
||||
}
|
||||
|
||||
10
src/mifare.h
10
src/mifare.h
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2009 Roel Verdult
|
||||
* 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
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -35,12 +35,12 @@
|
||||
*/
|
||||
|
||||
#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
|
||||
# pragma pack(1)
|
||||
#pragma pack(1)
|
||||
|
||||
typedef enum {
|
||||
MC_AUTH_A = 0x60,
|
||||
@@ -76,7 +76,7 @@ typedef union {
|
||||
// Reset struct alignment to default
|
||||
# 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
|
||||
# pragma pack(1)
|
||||
|
||||
@@ -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
|
||||
* Copyright (C) 2010, 2011 Romain Tartière
|
||||
* Copyright (C) 2009, 2010, 2011, 2012 Romuald Conty
|
||||
* Libnfc historical contributors:
|
||||
* Copyright (C) 2009 Roel Verdult
|
||||
* 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
|
||||
* 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
|
||||
print_nfc_target(const nfc_target nt, bool verbose)
|
||||
print_nfc_target(const nfc_target *pnt, bool verbose)
|
||||
{
|
||||
char *s;
|
||||
str_nfc_target(&s, nt, verbose);
|
||||
str_nfc_target(&s, pnt, verbose);
|
||||
printf("%s", s);
|
||||
free(s);
|
||||
nfc_free(s);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* Copyright (C) 2010 Romain Tartière
|
||||
* Copyright (C) 2010, 2011, 2012 Romuald Conty
|
||||
* Libnfc historical contributors:
|
||||
* Copyright (C) 2009 Roel Verdult
|
||||
* 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
|
||||
* 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_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
|
||||
|
||||
Reference in New Issue
Block a user