mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-24 15:05:29 -07:00
Merge 42654aacc0
into d889dacc9d
This commit is contained in:
commit
1d9e1b87df
20 changed files with 1977 additions and 135 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -15,6 +15,7 @@
|
|||
*.moc.cpp
|
||||
*.z
|
||||
*.exe
|
||||
hardnested_stats.txt
|
||||
proxmark
|
||||
proxmark3
|
||||
flasher
|
||||
|
|
|
@ -60,7 +60,8 @@ ARMSRC = fpgaloader.c \
|
|||
iclass.c \
|
||||
BigBuf.c \
|
||||
optimized_cipher.c \
|
||||
hfsnoop.c
|
||||
hfsnoop.c \
|
||||
parity.c
|
||||
|
||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||
include ../common/Makefile.common
|
||||
|
|
|
@ -428,7 +428,7 @@ void StandAloneMode14a()
|
|||
SpinDelay(300);
|
||||
}
|
||||
}
|
||||
if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid))
|
||||
if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid, true, 0))
|
||||
continue;
|
||||
else
|
||||
{
|
||||
|
@ -1126,6 +1126,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_MIFAREU_WRITEBL:
|
||||
MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES:
|
||||
MifareAcquireEncryptedNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
case CMD_MIFARE_NESTED:
|
||||
MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
|
||||
break;
|
||||
|
|
|
@ -123,6 +123,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
|
|
|
@ -526,7 +526,7 @@ int EPA_Setup()
|
|||
// power up the field
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
// select the card
|
||||
return_code = iso14443a_select_card(uid, &card_select_info, NULL);
|
||||
return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0);
|
||||
if (return_code == 1) {
|
||||
// send the PPS request
|
||||
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "cmd.h"
|
||||
|
||||
#include "iso14443crc.h"
|
||||
#include "iso14443a.h"
|
||||
#include "crapto1.h"
|
||||
#include "mifareutil.h"
|
||||
#include "BigBuf.h"
|
||||
#include "parity.h"
|
||||
|
||||
static uint32_t iso14a_timeout;
|
||||
int rsamples = 0;
|
||||
uint8_t trigger = 0;
|
||||
|
@ -122,26 +123,6 @@ static uint32_t LastProxToAirDuration;
|
|||
#define SEC_Y 0x00
|
||||
#define SEC_Z 0xc0
|
||||
|
||||
const uint8_t OddByteParity[256] = {
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
||||
};
|
||||
|
||||
|
||||
void iso14a_set_trigger(bool enable) {
|
||||
trigger = enable;
|
||||
}
|
||||
|
@ -179,11 +160,6 @@ void iso14a_set_ATS_timeout(uint8_t *ats) {
|
|||
// Generate the parity value for a byte sequence
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
byte_t oddparity (const byte_t bt)
|
||||
{
|
||||
return OddByteParity[bt];
|
||||
}
|
||||
|
||||
void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
|
||||
{
|
||||
uint16_t paritybit_cnt = 0;
|
||||
|
@ -192,7 +168,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
|
|||
|
||||
for (uint16_t i = 0; i < iLen; i++) {
|
||||
// Generate the parity bits
|
||||
parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt));
|
||||
parityBits |= ((oddparity8(pbtCmd[i])) << (7-paritybit_cnt));
|
||||
if (paritybit_cnt == 7) {
|
||||
par[paritybyte_cnt] = parityBits; // save 8 Bits parity
|
||||
parityBits = 0; // and advance to next Parity Byte
|
||||
|
@ -1695,10 +1671,12 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
|
|||
return Demod.len;
|
||||
}
|
||||
|
||||
/* performs iso14443a anticollision procedure
|
||||
* fills the uid pointer unless NULL
|
||||
* fills resp_data unless NULL */
|
||||
int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) {
|
||||
// performs iso14443a anticollision (optional) and card select procedure
|
||||
// fills the uid and cuid pointer unless NULL
|
||||
// fills the card info record unless NULL
|
||||
// if anticollision is false, then the UID must be provided in uid_ptr[]
|
||||
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
|
||||
int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades) {
|
||||
uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
|
||||
uint8_t sel_all[] = { 0x93,0x20 };
|
||||
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
|
@ -1713,7 +1691,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
|||
int len;
|
||||
|
||||
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
|
||||
ReaderTransmitBitsPar(wupa,7,0, NULL);
|
||||
ReaderTransmitBitsPar(wupa, 7, NULL, NULL);
|
||||
|
||||
// Receive the ATQA
|
||||
if(!ReaderReceive(resp, resp_par)) return 0;
|
||||
|
@ -1724,9 +1702,11 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
|||
memset(p_hi14a_card->uid,0,10);
|
||||
}
|
||||
|
||||
// clear uid
|
||||
if (uid_ptr) {
|
||||
memset(uid_ptr,0,10);
|
||||
if (anticollision) {
|
||||
// clear uid
|
||||
if (uid_ptr) {
|
||||
memset(uid_ptr,0,10);
|
||||
}
|
||||
}
|
||||
|
||||
// check for proprietary anticollision:
|
||||
|
@ -1741,40 +1721,49 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
|||
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
||||
|
||||
// SELECT_ALL
|
||||
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
if (anticollision) {
|
||||
// SELECT_ALL
|
||||
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
|
||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||
memset(uid_resp, 0, 4);
|
||||
uint16_t uid_resp_bits = 0;
|
||||
uint16_t collision_answer_offset = 0;
|
||||
// anti-collision-loop:
|
||||
while (Demod.collisionPos) {
|
||||
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
|
||||
for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
|
||||
uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01;
|
||||
uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8);
|
||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||
memset(uid_resp, 0, 4);
|
||||
uint16_t uid_resp_bits = 0;
|
||||
uint16_t collision_answer_offset = 0;
|
||||
// anti-collision-loop:
|
||||
while (Demod.collisionPos) {
|
||||
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
|
||||
for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
|
||||
uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01;
|
||||
uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
||||
uid_resp_bits++;
|
||||
// construct anticollosion command:
|
||||
sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
||||
for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
|
||||
sel_uid[2+i] = uid_resp[i];
|
||||
}
|
||||
collision_answer_offset = uid_resp_bits%8;
|
||||
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
|
||||
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
|
||||
}
|
||||
uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
||||
uid_resp_bits++;
|
||||
// construct anticollosion command:
|
||||
sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
||||
for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
|
||||
sel_uid[2+i] = uid_resp[i];
|
||||
// finally, add the last bits and BCC of the UID
|
||||
for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
|
||||
uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01;
|
||||
uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
collision_answer_offset = uid_resp_bits%8;
|
||||
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
|
||||
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
|
||||
}
|
||||
// finally, add the last bits and BCC of the UID
|
||||
for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
|
||||
uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01;
|
||||
uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8);
|
||||
}
|
||||
|
||||
} else { // no collision, use the response to SELECT_ALL as current uid
|
||||
memcpy(uid_resp, resp, 4);
|
||||
} else { // no collision, use the response to SELECT_ALL as current uid
|
||||
memcpy(uid_resp, resp, 4);
|
||||
}
|
||||
} else {
|
||||
if (cascade_level < num_cascades - 1) {
|
||||
uid_resp[0] = 0x88;
|
||||
memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3);
|
||||
} else {
|
||||
memcpy(uid_resp, uid_ptr+cascade_level*3, 4);
|
||||
}
|
||||
}
|
||||
uid_resp_len = 4;
|
||||
|
||||
|
@ -1785,7 +1774,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
|||
|
||||
// Construct SELECT UID command
|
||||
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
|
||||
memcpy(sel_uid+2, uid_resp, 4); // the UID
|
||||
memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID
|
||||
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
||||
AppendCrc14443a(sel_uid, 7); // calculate and add CRC
|
||||
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
|
||||
|
@ -1793,19 +1782,18 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
|||
// Receive the SAK
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
sak = resp[0];
|
||||
|
||||
// Test if more parts of the uid are coming
|
||||
|
||||
// Test if more parts of the uid are coming
|
||||
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
|
||||
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
|
||||
// http://www.nxp.com/documents/application_note/AN10927.pdf
|
||||
uid_resp[0] = uid_resp[1];
|
||||
uid_resp[1] = uid_resp[2];
|
||||
uid_resp[2] = uid_resp[3];
|
||||
|
||||
uid_resp_len = 3;
|
||||
}
|
||||
|
||||
if(uid_ptr) {
|
||||
if(uid_ptr && anticollision) {
|
||||
memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
|
||||
}
|
||||
|
||||
|
@ -1926,7 +1914,7 @@ void ReaderIso14443a(UsbCommand *c)
|
|||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
if(!(param & ISO14A_NO_SELECT)) {
|
||||
iso14a_card_select_t *card = (iso14a_card_select_t*)buf;
|
||||
arg0 = iso14443a_select_card(NULL,card,NULL);
|
||||
arg0 = iso14443a_select_card(NULL, card, NULL, true, 0);
|
||||
cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
|
||||
}
|
||||
}
|
||||
|
@ -2123,7 +2111,7 @@ void ReaderMifare(bool first_try)
|
|||
SpinDelay(100);
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card");
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -70,8 +70,6 @@ typedef struct {
|
|||
} tUart;
|
||||
|
||||
|
||||
|
||||
extern byte_t oddparity (const byte_t bt);
|
||||
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
||||
extern void AppendCrc14443a(uint8_t *data, int len);
|
||||
|
||||
|
@ -82,7 +80,6 @@ extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
|
|||
|
||||
extern void iso14443a_setup(uint8_t fpga_minor_mode);
|
||||
extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data);
|
||||
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr);
|
||||
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades);
|
||||
extern void iso14a_set_trigger(bool enable);
|
||||
|
||||
#endif /* __ISO14443A_H */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "crc.h"
|
||||
#include "parity.h"
|
||||
|
||||
// the block number for the ISO14443-4 PCB
|
||||
uint8_t pcb_blocknum = 0;
|
||||
|
@ -53,7 +54,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
@ -100,7 +101,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){
|
|||
|
||||
clear_trace();
|
||||
|
||||
if(!iso14443a_select_card(NULL, NULL, NULL)) {
|
||||
if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
|
||||
OnError(0);
|
||||
return;
|
||||
|
@ -135,7 +136,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
|
|||
|
||||
clear_trace();
|
||||
|
||||
int len = iso14443a_select_card(NULL, NULL, NULL);
|
||||
int len = iso14443a_select_card(NULL, NULL, NULL, true, 0);
|
||||
if(!len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);
|
||||
OnError(1);
|
||||
|
@ -211,7 +212,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
LED_C_OFF();
|
||||
|
||||
isOK = 1;
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
isOK = 0;
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
}
|
||||
|
@ -275,7 +276,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
return;
|
||||
}
|
||||
|
||||
int len = iso14443a_select_card(NULL, NULL, NULL);
|
||||
int len = iso14443a_select_card(NULL, NULL, NULL, true, 0);
|
||||
if (!len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);
|
||||
OnError(1);
|
||||
|
@ -377,7 +378,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
LED_C_OFF();
|
||||
|
||||
while (true) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
@ -431,7 +432,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
|
|||
clear_trace();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, NULL)) {
|
||||
if(!iso14443a_select_card(uid, NULL, NULL, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
OnError(0);
|
||||
return;
|
||||
|
@ -477,7 +478,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
|
|||
|
||||
clear_trace();
|
||||
|
||||
if(!iso14443a_select_card(NULL, NULL, NULL)) {
|
||||
if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
OnError(0);
|
||||
return;
|
||||
|
@ -536,7 +537,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
|
|||
|
||||
clear_trace();
|
||||
|
||||
if(!iso14443a_select_card(NULL, NULL, NULL)) {
|
||||
if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
OnError(0);
|
||||
return;
|
||||
|
@ -595,9 +596,141 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
|
|||
|
||||
// Return 1 if the nonce is invalid else return 0
|
||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
|
||||
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
||||
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
|
||||
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
|
||||
return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
||||
(oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
|
||||
(oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// acquire encrypted nonces in order to perform the attack described in
|
||||
// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened
|
||||
// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on
|
||||
// Computer and Communications Security, 2015
|
||||
//-----------------------------------------------------------------------------
|
||||
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain)
|
||||
{
|
||||
uint64_t ui64Key = 0;
|
||||
uint8_t uid[10];
|
||||
uint32_t cuid;
|
||||
uint8_t cascade_levels = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
|
||||
int16_t isOK = 0;
|
||||
uint8_t par_enc[1];
|
||||
uint8_t nt_par_enc = 0;
|
||||
uint8_t buf[USB_CMD_DATA_SIZE];
|
||||
uint32_t timeout;
|
||||
|
||||
uint8_t blockNo = arg0 & 0xff;
|
||||
uint8_t keyType = (arg0 >> 8) & 0xff;
|
||||
uint8_t targetBlockNo = arg1 & 0xff;
|
||||
uint8_t targetKeyType = (arg1 >> 8) & 0xff;
|
||||
ui64Key = bytes_to_num(datain, 6);
|
||||
bool initialize = flags & 0x0001;
|
||||
bool slow = flags & 0x0002;
|
||||
bool field_off = flags & 0x0004;
|
||||
|
||||
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
||||
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
|
||||
|
||||
LED_A_ON();
|
||||
LED_C_OFF();
|
||||
|
||||
if (initialize) {
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
}
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
uint16_t num_nonces = 0;
|
||||
bool have_uid = false;
|
||||
for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) {
|
||||
|
||||
// Test if the action was cancelled
|
||||
if(BUTTON_PRESS()) {
|
||||
isOK = 2;
|
||||
field_off = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_uid) { // need a full select cycle to get the uid first
|
||||
iso14a_card_select_t card_info;
|
||||
if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");
|
||||
continue;
|
||||
}
|
||||
switch (card_info.uidlen) {
|
||||
case 4 : cascade_levels = 1; break;
|
||||
case 7 : cascade_levels = 2; break;
|
||||
case 10: cascade_levels = 3; break;
|
||||
default: break;
|
||||
}
|
||||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (slow) {
|
||||
timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME;
|
||||
while(GetCountSspClk() < timeout);
|
||||
}
|
||||
|
||||
uint32_t nt1;
|
||||
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");
|
||||
continue;
|
||||
}
|
||||
|
||||
// nested authentication
|
||||
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);
|
||||
if (len != 4) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);
|
||||
continue;
|
||||
}
|
||||
|
||||
// send a dummy byte as reader response in order to trigger the cards authentication timeout
|
||||
uint8_t dummy_answer = 0;
|
||||
ReaderTransmit(&dummy_answer, 1, NULL);
|
||||
timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
|
||||
|
||||
num_nonces++;
|
||||
if (num_nonces % 2) {
|
||||
memcpy(buf+i, receivedAnswer, 4);
|
||||
nt_par_enc = par_enc[0] & 0xf0;
|
||||
} else {
|
||||
nt_par_enc |= par_enc[0] >> 4;
|
||||
memcpy(buf+i+4, receivedAnswer, 4);
|
||||
memcpy(buf+i+8, &nt_par_enc, 1);
|
||||
i += 9;
|
||||
}
|
||||
|
||||
// wait for the card to become ready again
|
||||
while(GetCountSspClk() < timeout);
|
||||
|
||||
}
|
||||
|
||||
LED_C_OFF();
|
||||
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
LED_B_ON();
|
||||
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
|
||||
LED_B_OFF();
|
||||
|
||||
if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");
|
||||
|
||||
if (field_off) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -672,7 +805,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
continue;
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
|
||||
rtr--;
|
||||
continue;
|
||||
|
@ -746,7 +879,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
continue;
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
|
||||
continue;
|
||||
};
|
||||
|
@ -770,7 +903,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
|
||||
// Parity validity check
|
||||
for (j = 0; j < 4; j++) {
|
||||
par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
|
||||
par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
|
||||
}
|
||||
|
||||
ncount = 0;
|
||||
|
@ -861,7 +994,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error");
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card");
|
||||
break;
|
||||
};
|
||||
|
@ -954,7 +1087,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
|
||||
bool isOK = true;
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
isOK = false;
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
}
|
||||
|
@ -1054,7 +1187,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
|
||||
// get UID from chip
|
||||
if (workFlags & 0x01) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
@ -1259,7 +1392,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
|
|||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
clear_trace();
|
||||
|
||||
int len = iso14443a_select_card(uid, NULL, &cuid);
|
||||
int len = iso14443a_select_card(uid, NULL, &cuid, true, 0);
|
||||
if(!len) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
|
||||
OnError(1);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "iso14443a.h"
|
||||
#include "crapto1.h"
|
||||
#include "mifareutil.h"
|
||||
#include "parity.h"
|
||||
#include "des.h"
|
||||
|
||||
int MF_DBGLEVEL = MF_DBG_ALL;
|
||||
|
@ -50,7 +51,7 @@ void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, u
|
|||
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
|
||||
if((i&0x0007) == 0)
|
||||
par[i>>3] = 0;
|
||||
par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007)));
|
||||
par[i>>3] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -99,7 +100,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
|
|||
for (pos = 0; pos < 4; pos++)
|
||||
{
|
||||
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos));
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos));
|
||||
}
|
||||
|
||||
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
|
||||
|
@ -193,7 +194,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
|||
for (pos = 0; pos < 4; pos++)
|
||||
{
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos));
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos));
|
||||
}
|
||||
|
||||
// Skip 32 bits in pseudo random generator
|
||||
|
@ -204,7 +205,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
|||
{
|
||||
nt = prng_successor(nt,8);
|
||||
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos));
|
||||
par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos));
|
||||
}
|
||||
|
||||
// Transmit reader nonce and reader answer
|
||||
|
@ -427,7 +428,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
|||
for (pos = 0; pos < 18; pos++)
|
||||
{
|
||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
||||
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
|
||||
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
|
||||
}
|
||||
|
||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
||||
|
|
|
@ -66,6 +66,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
loclass/elite_crack.c\
|
||||
loclass/fileutils.c\
|
||||
mifarehost.c\
|
||||
parity.c\
|
||||
crc.c \
|
||||
crc16.c \
|
||||
crc64.c \
|
||||
|
@ -85,6 +86,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
cmdhficlass.c \
|
||||
cmdhfmf.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhfmfhard.c \
|
||||
cmdhftopaz.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
|
|
174
client/cmdhfmf.c
174
client/cmdhfmf.c
|
@ -9,6 +9,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhfmfhard.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -784,6 +785,124 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfNestedHard(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
uint8_t keyType = 0;
|
||||
uint8_t trgBlockNo = 0;
|
||||
uint8_t trgKeyType = 0;
|
||||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
char ctmp;
|
||||
ctmp = param_getchar(Cmd, 0);
|
||||
|
||||
if (ctmp != 'R' && ctmp != 'r' && ctmp != 'T' && ctmp != 't' && strlen(Cmd) < 20) {
|
||||
PrintAndLog("Usage:");
|
||||
PrintAndLog(" hf mf hardnested <block number> <key A|B> <key (12 hex symbols)>");
|
||||
PrintAndLog(" <target block number> <target key A|B> [known target key (12 hex symbols)] [w] [s]");
|
||||
PrintAndLog(" or hf mf hardnested r [known target key]");
|
||||
PrintAndLog(" ");
|
||||
PrintAndLog("Options: ");
|
||||
PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin");
|
||||
PrintAndLog(" s: Slower acquisition (required by some non standard cards)");
|
||||
PrintAndLog(" r: Read nonces.bin and start attack");
|
||||
PrintAndLog(" ");
|
||||
PrintAndLog(" sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A");
|
||||
PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w");
|
||||
PrintAndLog(" sample3: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w s");
|
||||
PrintAndLog(" sample4: hf mf hardnested r");
|
||||
PrintAndLog(" ");
|
||||
PrintAndLog("Add the known target key to check if it is present in the remaining key space:");
|
||||
PrintAndLog(" sample5: hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool know_target_key = false;
|
||||
bool nonce_file_read = false;
|
||||
bool nonce_file_write = false;
|
||||
bool slow = false;
|
||||
int tests = 0;
|
||||
|
||||
|
||||
if (ctmp == 'R' || ctmp == 'r') {
|
||||
nonce_file_read = true;
|
||||
if (!param_gethex(Cmd, 1, trgkey, 12)) {
|
||||
know_target_key = true;
|
||||
}
|
||||
} else if (ctmp == 'T' || ctmp == 't') {
|
||||
tests = param_get32ex(Cmd, 1, 100, 10);
|
||||
} else {
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
ctmp = param_getchar(Cmd, 1);
|
||||
if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {
|
||||
PrintAndLog("Key type must be A or B");
|
||||
return 1;
|
||||
}
|
||||
if (ctmp != 'A' && ctmp != 'a') {
|
||||
keyType = 1;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 2, key, 12)) {
|
||||
PrintAndLog("Key must include 12 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
trgBlockNo = param_get8(Cmd, 3);
|
||||
ctmp = param_getchar(Cmd, 4);
|
||||
if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {
|
||||
PrintAndLog("Target key type must be A or B");
|
||||
return 1;
|
||||
}
|
||||
if (ctmp != 'A' && ctmp != 'a') {
|
||||
trgKeyType = 1;
|
||||
}
|
||||
|
||||
uint16_t i = 5;
|
||||
|
||||
if (!param_gethex(Cmd, 5, trgkey, 12)) {
|
||||
know_target_key = true;
|
||||
i++;
|
||||
}
|
||||
|
||||
while ((ctmp = param_getchar(Cmd, i))) {
|
||||
if (ctmp == 's' || ctmp == 'S') {
|
||||
slow = true;
|
||||
} else if (ctmp == 'w' || ctmp == 'W') {
|
||||
nonce_file_write = true;
|
||||
} else {
|
||||
PrintAndLog("Possible options are w and/or s");
|
||||
return 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ",
|
||||
trgBlockNo,
|
||||
trgKeyType?'B':'A',
|
||||
trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5],
|
||||
know_target_key?"":" (not set)",
|
||||
nonce_file_write?"write":nonce_file_read?"read":"none",
|
||||
slow?"Yes":"No",
|
||||
tests);
|
||||
|
||||
int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key?trgkey:NULL, nonce_file_read, nonce_file_write, slow, tests);
|
||||
|
||||
if (isOK) {
|
||||
switch (isOK) {
|
||||
case 1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
|
||||
case 2 : PrintAndLog("Button pressed. Aborted.\n"); break;
|
||||
default : break;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfChk(const char *Cmd)
|
||||
{
|
||||
if (strlen(Cmd)<3) {
|
||||
|
@ -1961,33 +2080,34 @@ int CmdDecryptTraceCmds(const char *Cmd){
|
|||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
|
||||
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
|
||||
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},
|
||||
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
|
||||
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
||||
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},
|
||||
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
|
||||
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},
|
||||
{"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},
|
||||
{"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},
|
||||
{"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},
|
||||
{"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},
|
||||
{"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},
|
||||
{"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},
|
||||
{"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},
|
||||
{"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},
|
||||
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
|
||||
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
|
||||
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
|
||||
{"decrypt", CmdDecryptTraceCmds,1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
{"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},
|
||||
{"chk", CmdHF14AMfChk, 0, "Test block keys"},
|
||||
{"mifare", CmdHF14AMifare, 0, "Read parity error messages."},
|
||||
{"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
|
||||
{"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},
|
||||
{"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
|
||||
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},
|
||||
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
|
||||
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},
|
||||
{"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},
|
||||
{"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},
|
||||
{"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},
|
||||
{"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},
|
||||
{"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},
|
||||
{"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},
|
||||
{"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},
|
||||
{"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},
|
||||
{"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},
|
||||
{"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},
|
||||
{"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},
|
||||
{"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdHFMF(const char *Cmd)
|
||||
|
|
1476
client/cmdhfmfhard.c
Normal file
1476
client/cmdhfmfhard.c
Normal file
File diff suppressed because it is too large
Load diff
11
client/cmdhfmfhard.h
Normal file
11
client/cmdhfmfhard.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2015 piwi
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// hf mf hardnested command
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests);
|
|
@ -126,6 +126,7 @@ local _commands = {
|
|||
|
||||
CMD_READER_MIFARE = 0x0611,
|
||||
CMD_MIFARE_NESTED = 0x0612,
|
||||
CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES = 0x0613,
|
||||
|
||||
CMD_MIFARE_READBL = 0x0620,
|
||||
CMD_MIFAREU_READBL = 0x0720,
|
||||
|
|
|
@ -193,6 +193,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){
|
||||
|
||||
*key = 0;
|
||||
|
|
|
@ -21,14 +21,20 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#if !defined LOWMEM && defined __GNUC__
|
||||
static uint8_t filterlut[1 << 20];
|
||||
uint8_t filterlut[1 << 20];
|
||||
static void __attribute__((constructor)) fill_lut()
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < 1 << 20; ++i)
|
||||
filterlut[i] = filter(i);
|
||||
uint32_t x;
|
||||
uint32_t f;
|
||||
for(x = 0; x < 1 << 20; ++x) {
|
||||
f = 0xf22c0 >> (x & 0xf) & 16;
|
||||
f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8;
|
||||
f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4;
|
||||
f |= 0x1e458 >> (x >> 12 & 0xf) & 2;
|
||||
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
|
||||
filterlut[x] = BIT(0xEC57E80A, f);
|
||||
}
|
||||
}
|
||||
#define filter(x) (filterlut[(x) & 0xfffff])
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,12 @@ static inline int parity(uint32_t x)
|
|||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined LOWMEM && defined __GNUC__
|
||||
extern uint8_t filterlut[1 << 20];
|
||||
#define filter(x) (filterlut[(x) & 0xfffff])
|
||||
#define filter_unsafe(x) (filterlut[x])
|
||||
#else
|
||||
static inline int filter(uint32_t const x)
|
||||
{
|
||||
uint32_t f;
|
||||
|
@ -91,6 +97,9 @@ static inline int filter(uint32_t const x)
|
|||
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
|
||||
return BIT(0xEC57E80A, f);
|
||||
}
|
||||
#define filter_unsafe(x) (filter(x))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
49
common/parity.c
Normal file
49
common/parity.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// parity functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
const uint8_t OddByteParity[256] = {
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
||||
};
|
||||
|
||||
const uint8_t EvenByteParity[256] = {
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
|
||||
};
|
||||
|
||||
|
41
common/parity.h
Normal file
41
common/parity.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generic CRC calculation code.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __PARITY_H
|
||||
#define __PARITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern const uint8_t OddByteParity[256];
|
||||
|
||||
#define oddparity8(x) (OddByteParity[(x)])
|
||||
|
||||
|
||||
extern const uint8_t EvenByteParity[256];
|
||||
|
||||
static inline bool /*__attribute__((always_inline))*/ evenparity8(const uint8_t x) {
|
||||
#if !defined __i386__ || !defined __GNUC__
|
||||
return EvenByteParity[x];
|
||||
#else
|
||||
uint8_t y;
|
||||
__asm( "testb $255, %1\n"
|
||||
"setpo %0\n" : "=r"(y) : "r"(x): );
|
||||
return y;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline uint8_t evenparity32(uint32_t x)
|
||||
{
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
return EvenByteParity[x & 0xff];
|
||||
}
|
||||
|
||||
|
||||
#endif /* __PARITY_H */
|
|
@ -172,6 +172,7 @@ typedef struct{
|
|||
|
||||
#define CMD_READER_MIFARE 0x0611
|
||||
#define CMD_MIFARE_NESTED 0x0612
|
||||
#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613
|
||||
|
||||
#define CMD_MIFARE_READBL 0x0620
|
||||
#define CMD_MIFAREU_READBL 0x0720
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue