add: 'hf mf personalize' (personalize UID on Mifare Classic EV1 7byte UID cards)

* add/use some #defines
* whitespace fixes
* #include refactoring
* add line to CHANGELOG.md
This commit is contained in:
pwpiwi 2019-08-22 07:53:17 +02:00 committed by GitHub
parent cfa9c98d57
commit 0b4efbdef2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 514 additions and 369 deletions

View file

@ -42,6 +42,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added downlink reference mode option r <mode> [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce` - Added downlink reference mode option r <mode> [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce`
- Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password - Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password
- `hf mfu info` now checks the NXP Originality Signature if availabe (piwi) - `hf mfu info` now checks the NXP Originality Signature if availabe (piwi)
- Added `hf mf personalize` to personalize the UID option of Mifare Classic EV1 cards (piwi)
## [v3.1.0][2018-10-10] ## [v3.1.0][2018-10-10]

View file

@ -28,6 +28,7 @@
#include "iso15693.h" #include "iso15693.h"
#include "lfsampling.h" #include "lfsampling.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "mifarecmd.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "mifaresim.h" #include "mifaresim.h"
#include "pcf7931.h" #include "pcf7931.h"
@ -1242,6 +1243,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFARE_WRITEBL: case CMD_MIFARE_WRITEBL:
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
case CMD_MIFARE_PERSONALIZE_UID:
MifarePersonalizeUID(c->arg[0], c->arg[1], c->d.asBytes);
break;
//case CMD_MIFAREU_WRITEBL_COMPAT: //case CMD_MIFAREU_WRITEBL_COMPAT:
//MifareUWriteBlockCompat(c->arg[0], c->d.asBytes); //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
//break; //break;

View file

@ -108,33 +108,6 @@ void RAMFUNC SniffMifare(uint8_t param);
void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Collect_Nonce(UsbCommand * c);
void EPA_PACE_Replay(UsbCommand *c); void EPA_PACE_Replay(UsbCommand *c);
// mifarecmd.h
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUC_Auth(uint8_t arg0, uint8_t *datain);
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
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, uint16_t arg1, uint8_t arg2, uint8_t *datain);
void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCIdent(); // is "magic chinese" card?
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
//desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// mifaredesfire.h // mifaredesfire.h
bool InitDesfireCard(); bool InitDesfireCard();
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain); void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);

View file

@ -15,6 +15,16 @@
#include "mifarecmd.h" #include "mifarecmd.h"
#include <stdint.h>
#include "proxmark3.h"
#include "cmd.h"
#include "crapto1/crapto1.h"
#include "iso14443a.h"
#include "BigBuf.h"
#include "mifareutil.h"
#include "apps.h"
#include "protocols.h"
#include "util.h" #include "util.h"
#include "parity.h" #include "parity.h"
#include "crc.h" #include "crc.h"
@ -1026,6 +1036,60 @@ void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
LED_A_OFF(); LED_A_OFF();
} }
//-----------------------------------------------------------------------------
// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID
//-----------------------------------------------------------------------------
void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *data) {
uint8_t uid[10];
uint32_t cuid;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
LED_A_ON();
clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
bool isOK = false;
while (true) {
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break;
}
uint8_t block_number = 0;
uint64_t key = bytes_to_num(data, 6);
if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
break;
}
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL);
if (len != 1 || receivedAnswer[0] != CARD_ACK) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
break;;
}
isOK = true;
break;
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
crypto1_destroy(pcs);
if (MF_DBGLEVEL >= 2) DbpString("PERSONALIZE UID FINISHED");
cmd_send(CMD_ACK, isOK, 0, 0, NULL, 0);
LED_A_OFF();
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// MIFARE commands set debug level // MIFARE commands set debug level
// //
@ -1201,13 +1265,13 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
// wipe // wipe
if (needWipe){ if (needWipe){
ReaderTransmitBitsPar(wupC1,7,0, NULL); ReaderTransmitBitsPar(wupC1,7,0, NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
break; break;
}; };
ReaderTransmit(wipeC, sizeof(wipeC), NULL); ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
break; break;
}; };
@ -1222,16 +1286,16 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
// select commands // select commands
ReaderTransmitBitsPar(wupC1, 7, 0, NULL); ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
// gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) // gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)
if (!gen1b) { if (!gen1b) {
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
break; break;
}; };
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
break; break;
}; };
@ -1239,7 +1303,7 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
// send blocks command // send blocks command
for (int blockNo = 0; blockNo < numBlocks; blockNo++) { for (int blockNo = 0; blockNo < numBlocks; blockNo++) {
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
break; break;
}; };
@ -1257,7 +1321,7 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
// send write command // send write command
ReaderTransmit(d_block, sizeof(d_block), NULL); ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
break; break;
}; };
@ -1346,13 +1410,13 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
// Wipe command don't work with gen1b // Wipe command don't work with gen1b
if (needWipe && !(workFlags & 0x40)){ if (needWipe && !(workFlags & 0x40)){
ReaderTransmitBitsPar(wupC1,7,0, NULL); ReaderTransmitBitsPar(wupC1,7,0, NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
break; break;
}; };
ReaderTransmit(wipeC, sizeof(wipeC), NULL); ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
break; break;
}; };
@ -1368,23 +1432,23 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if (workFlags & 0x02) { if (workFlags & 0x02) {
ReaderTransmitBitsPar(wupC1,7,0, NULL); ReaderTransmitBitsPar(wupC1,7,0, NULL);
// gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) // gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)
if (!(workFlags & 0x40)) { if (!(workFlags & 0x40)) {
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
break; break;
}; };
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
break; break;
}; };
} }
} }
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
break; break;
}; };
@ -1393,7 +1457,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
AppendCrc14443a(d_block, 16); AppendCrc14443a(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL); ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
break; break;
}; };
@ -1461,14 +1525,14 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
while (true) { while (true) {
if (workFlags & 0x02) { if (workFlags & 0x02) {
ReaderTransmitBitsPar(wupC1,7,0, NULL); ReaderTransmitBitsPar(wupC1,7,0, NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
break; break;
}; };
// do no issue for gen1b magic tag // do no issue for gen1b magic tag
if (!(workFlags & 0x40)) { if (!(workFlags & 0x40)) {
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
break; break;
}; };
@ -1533,11 +1597,11 @@ void MifareCIdent(){
set_tracing(true); set_tracing(true);
ReaderTransmitBitsPar(wupC1,7,0, NULL); ReaderTransmitBitsPar(wupC1,7,0, NULL);
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) { if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {
isOK = 2; isOK = 2;
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) { if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {
isOK = 1; isOK = 1;
}; };
}; };

View file

@ -10,18 +10,36 @@
// Routines to support ISO 14443 type A. // Routines to support ISO 14443 type A.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __MIFARECMD_H #ifndef MIFARECMD_H__
#define __MIFARECMD_H #define MIFARECMD_H__
#include "proxmark3.h" #include <stdint.h>
#include "apps.h"
#include "util.h"
#include "iso14443crc.h" extern void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
#include "iso14443a.h" extern void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
#include "crapto1/crapto1.h" extern void MifareUC_Auth(uint8_t arg0, uint8_t *datain);
#include "mifareutil.h" extern void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
#include "common.h" extern void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
extern void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
//extern void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
extern void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
extern void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
extern void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
extern void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card
extern void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
extern void MifareCIdent(); // is "magic chinese" card?
extern void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
extern void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *datain);
//desfire
extern void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
extern void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
#endif #endif

View file

@ -22,6 +22,7 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "mbedtls/des.h" #include "mbedtls/des.h"
#include "protocols.h"
int MF_DBGLEVEL = MF_DBG_INFO; int MF_DBGLEVEL = MF_DBG_INFO;
@ -163,7 +164,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// Transmit MIFARE_CLASSIC_AUTH // Transmit MIFARE_CLASSIC_AUTH
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); len = mifare_sendcmd_short(pcs, isNested, keyType & 0x01 ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, blockNo, receivedAnswer, receivedAnswerPar, timing);
if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len); if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len);
if (len != 4) return 1; if (len != 4) return 1;
@ -250,7 +251,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// command MIFARE_CLASSIC_READBLOCK // command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return 1;
@ -282,7 +283,7 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) if (MF_DBGLEVEL >= MF_DBG_EXTENDED)
Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);
len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL); len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL);
//len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL); //len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);
if (len != 4) { if (len != 4) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);
@ -314,7 +315,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
uint8_t respPar[3] = {0,0,0}; uint8_t respPar[3] = {0,0,0};
// REQUEST AUTHENTICATION // REQUEST AUTHENTICATION
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL); len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL);
if (len != 11) { if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0; return 0;
@ -364,7 +365,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
); );
//len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL); //len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);
len = mifare_sendcmd(0xAF, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
if (len != 11) { if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0; return 0;
@ -421,7 +422,7 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
int result = 0; int result = 0;
for (retries = 0; retries < MFU_MAX_RETRIES; retries++) { for (retries = 0; retries < MFU_MAX_RETRIES; retries++) {
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
result = 1; result = 1;
@ -468,7 +469,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// command MIFARE_CLASSIC_WRITEBLOCK // command MIFARE_CLASSIC_WRITEBLOCK
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
@ -511,7 +512,7 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData)
uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswer[MAX_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE];
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, true, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
@ -563,7 +564,7 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL);
if (len != 0) { if (len != 0) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("halt error. response len: %x", len); Dbprintf("halt error. response len: %x", len);
@ -579,7 +580,7 @@ int mifare_ultra_halt()
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL);
if (len != 0) { if (len != 0) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (MF_DBGLEVEL >= MF_DBG_ERROR)
Dbprintf("halt error. response len: %x", len); Dbprintf("halt error. response len: %x", len);

View file

@ -34,6 +34,7 @@
#include "mifare/mad.h" #include "mifare/mad.h"
#include "mifare/ndef.h" #include "mifare/ndef.h"
#include "emv/dump.h" #include "emv/dump.h"
#include "protocols.h"
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up #define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
@ -3009,8 +3010,86 @@ int CmdHFMFNDEF(const char *cmd) {
return 0; return 0;
} }
static command_t CommandTable[] = int CmdHFMFPersonalize(const char *cmd) {
{
CLIParserInit("hf mf personalize",
"Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",
"Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"
"\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"
"\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n"
"\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n"
"\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n");
void *argtable[] = {
arg_param_begin,
arg_str0("tT", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),
arg_str0("kK", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),
arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, true);
char keytypestr[2] = "A";
uint8_t keytype = 0x00;
int keytypestr_len;
int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len);
if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'A' && keytypestr[0] != 'b' && keytypestr[0] != 'B')) {
PrintAndLog("ERROR: not a valid key type. Key type must be A or B");
CLIParserFree();
return 1;
}
if (keytypestr[0] == 'B' || keytypestr[0] == 'b') {
keytype = 0x01;
}
uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int key_len;
res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len);
if (res || (!res && key_len > 0 && key_len != 6)) {
PrintAndLog("ERROR: not a valid key. Key must be 12 hex digits");
CLIParserFree();
return 1;
}
char pers_optionstr[6];
int opt_len;
uint8_t pers_option;
res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len);
if (res || (!res && opt_len > 0 && opt_len != 5)
|| (strncmp(pers_optionstr, "UIDF0", 5) && strncmp(pers_optionstr, "UIDF1", 5) && strncmp(pers_optionstr, "UIDF2", 5) && strncmp(pers_optionstr, "UIDF3", 5))) {
PrintAndLog("ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3");
CLIParserFree();
return 1;
}
if (!strncmp(pers_optionstr, "UIDF0", 5)) {
pers_option = MIFARE_EV1_UIDF0;
} else if (!strncmp(pers_optionstr, "UIDF1", 5)) {
pers_option = MIFARE_EV1_UIDF1;
} else if (!strncmp(pers_optionstr, "UIDF2", 5)) {
pers_option = MIFARE_EV1_UIDF2;
} else {
pers_option = MIFARE_EV1_UIDF3;
}
CLIParserFree();
UsbCommand c = {CMD_MIFARE_PERSONALIZE_UID, {keytype, pers_option, 0}};
memcpy(c.d.asBytes, key, 6);
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("Personalization %s", isOK ? "FAILED" : "SUCCEEDED");
} else {
PrintAndLog("Command execute timeout");
}
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
@ -3042,18 +3121,19 @@ static command_t CommandTable[] =
{"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
{"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},
{"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"}, {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},
{"personalize", CmdHFMFPersonalize, 0, "Personalize UID (Mifare Classic EV1 only)"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdHFMF(const char *Cmd)
{ int CmdHFMF(const char *Cmd) {
(void)WaitForResponseTimeout(CMD_ACK,NULL,100); (void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);
return 0; return 0;
} }
int CmdHelp(const char *Cmd)
{ int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

@ -125,6 +125,10 @@ NXP/Philips CUSTOM COMMANDS
#define MIFARE_CMD_TRANSFER 0xB0 #define MIFARE_CMD_TRANSFER 0xB0
#define MIFARE_EV1_PERSONAL_UID 0x40 #define MIFARE_EV1_PERSONAL_UID 0x40
#define MIFARE_EV1_UIDF0 0x00
#define MIFARE_EV1_UIDF1 0x40
#define MIFARE_EV1_UIDF2 0x20
#define MIFARE_EV1_UIDF3 0x60
#define MIFARE_EV1_SETMODE 0x43 #define MIFARE_EV1_SETMODE 0x43
#define MIFARE_ULC_WRITE 0xA2 #define MIFARE_ULC_WRITE 0xA2

View file

@ -197,17 +197,17 @@ typedef struct{
#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613 #define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613
#define CMD_MIFARE_READBL 0x0620 #define CMD_MIFARE_READBL 0x0620
#define CMD_MIFAREU_READBL 0x0720
#define CMD_MIFARE_READSC 0x0621 #define CMD_MIFARE_READSC 0x0621
#define CMD_MIFAREU_READCARD 0x0721
#define CMD_MIFARE_WRITEBL 0x0622 #define CMD_MIFARE_WRITEBL 0x0622
#define CMD_MIFARE_CHKKEYS 0x0623
#define CMD_MIFARE_PERSONALIZE_UID 0x0624
#define CMD_MIFARE_SNIFFER 0x0630
//ultralightC
#define CMD_MIFAREU_READBL 0x0720
#define CMD_MIFAREU_READCARD 0x0721
#define CMD_MIFAREU_WRITEBL 0x0722 #define CMD_MIFAREU_WRITEBL 0x0722
#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 #define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
#define CMD_MIFARE_CHKKEYS 0x0623
#define CMD_MIFARE_SNIFFER 0x0630
//ultralightC
#define CMD_MIFAREUC_AUTH 0x0724 #define CMD_MIFAREUC_AUTH 0x0724
//0x0725 and 0x0726 no longer used //0x0725 and 0x0726 no longer used
#define CMD_MIFAREUC_SETPWD 0x0727 #define CMD_MIFAREUC_SETPWD 0x0727