// Routines to support ISO 14443 type A.
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
-#include "cmd.h"
-
-#include "iso14443crc.h"
+#include "../common/cmd.h"
+#include "../common/iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#define SEC_Y 0x00
#define SEC_Z 0xc0
+//replaced large parity table with small parity generation function - saves flash code
+/*
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
};
-
+*/
void iso14a_set_trigger(bool enable) {
trigger = enable;
// Generate the parity value for a byte sequence
//
//-----------------------------------------------------------------------------
+/*
byte_t oddparity (const byte_t bt)
{
return OddByteParity[bt];
}
+*/
uint32_t GetParity(const uint8_t * pbtCmd, int iLen)
{
// Generate the parity bits
for (i = 0; i < iLen; i++) {
// and save them to a 32Bit word
- dwPar |= ((OddByteParity[pbtCmd[i]]) << i);
+ //dwPar |= ((OddByteParity[pbtCmd[i]]) << i);
+ dwPar |= (oddparity(pbtCmd[i]) << i);
}
return dwPar;
}
LEDsoff();
// init trace buffer
iso14a_clear_trace();
+ iso14a_set_tracing(TRUE);
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
}
// Get the parity bit
- if ((dwParity >> i) & 0x01) {
+ //if ((dwParity >> i) & 0x01) {
+ if (oddparity(cmd[i]) & 0x01) {
ToSend[++ToSendMax] = SEC_D;
LastProxToAirDuration = 8 * ToSendMax - 4;
} else {
response1[1] = 0x00;
sak = 0x28;
} break;
+ case 5: { // MIFARE TNP3XXX
+ // Says: I am a toy
+ response1[0] = 0x01;
+ response1[1] = 0x0f;
+ sak = 0x01;
+ } break;
default: {
Dbprintf("Error: unkown tagtype (%d)",tagType);
return;
// clear TXRDY
AT91C_BASE_SSC->SSC_THR = SEC_Y;
- // for(uint16_t c = 0; c < 10;) { // standard delay for each transfer (allow tag to be ready after last transmission)
- // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- // AT91C_BASE_SSC->SSC_THR = SEC_Y;
- // c++;
- // }
- // }
-
uint16_t c = 0;
for(;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
}
}
- NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME);
-
+ NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME);
}
memcpy(uid_resp,resp,4);
}
uid_resp_len = 4;
- // Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]);
+
// calculate crypto UID. Always use last 4 Bytes.
if(cuid_ptr) {
if (!ReaderReceive(resp)) return 0;
sak = resp[0];
+ //Dbprintf("SAK: %02x",resp[0]);
+
// Test if more parts of the uid are comming
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
- memcpy(uid_resp, uid_resp + 1, 3);
+ // This was earlier:
+ //memcpy(uid_resp, uid_resp + 1, 3);
+ // But memcpy should not be used for overlapping arrays,
+ // and memmove appears to not be available in the arm build.
+ // So this has been replaced with a for-loop:
+ for(int xx = 0; xx < 3; xx++)
+ uid_resp[xx] = uid_resp[xx+1];
uid_resp_len = 3;
}
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Signal field is on with the appropriate LED
- if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD
- || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
+ if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
LED_D_ON();
} else {
LED_D_OFF();
DemodReset();
UartReset();
NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
- iso14a_set_timeout(1050); // 10ms default
+ iso14a_set_timeout(1050); // 10ms default 10*105 =
}
int iso14_apdu(uint8_t * cmd, size_t cmd_len, void * data) {
{
iso14a_command_t param = c->arg[0];
uint8_t *cmd = c->d.asBytes;
- size_t len = c->arg[1];
- size_t lenbits = c->arg[2];
+ size_t len = c->arg[1] & 0xFFFF;
+ size_t lenbits = c->arg[1] >> 16;
uint32_t arg0 = 0;
byte_t buf[USB_CMD_DATA_SIZE];
}
if(param & ISO14A_SET_TIMEOUT) {
- iso14a_timeout = c->arg[2];
+ iso14a_set_timeout(c->arg[2]);
}
if(param & ISO14A_APDU) {
if(param & ISO14A_APPEND_CRC) {
AppendCrc14443a(cmd,len);
len += 2;
- lenbits += 16;
+ if(lenbits>0)
+ lenbits += 16;
}
- if(lenbits>0) {
-
+ if(lenbits>0) {
ReaderTransmitBitsPar(cmd,lenbits,GetParity(cmd,lenbits/8), NULL);
} else {
ReaderTransmit(cmd,len, NULL);
uint8_t uid[10];
uint32_t cuid;
- uint32_t nt, previous_nt;
+ uint32_t nt = 0;
+ uint32_t previous_nt = 0;
static uint32_t nt_attacked = 0;
- byte_t par_list[8] = {0,0,0,0,0,0,0,0};
- byte_t ks_list[8] = {0,0,0,0,0,0,0,0};
+ byte_t par_list[8] = {0x00};
+ byte_t ks_list[8] = {0x00};
static uint32_t sync_time;
static uint32_t sync_cycles;
uint16_t consecutive_resyncs = 0;
int isOK = 0;
-
-
if (first_try) {
mf_nr_ar3 = 0;
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
LED_C_OFF();
+ Dbprintf("Mifare: Before loopen");
for(uint16_t i = 0; TRUE; i++) {
WDT_HIT();
// select card
if (len == 9 &&
(receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
- EmSendCmd(_7BUID?rSAK1:rSAK, sizeof(_7BUID?rSAK1:rSAK));
+ EmSendCmd(_7BUID?rSAK1:rSAK, _7BUID?sizeof(rSAK1):sizeof(rSAK));
cuid = bytes_to_num(rUIDBCC1, 4);
if (!_7BUID) {
cardSTATE = MFEMUL_WORK;
// Shouldn't we respond anything here?
// Right now, we don't nack or anything, which causes the
// reader to do a WUPA after a while. /Martin
+ // -- which is the correct response. /piwi
cardSTATE_TO_IDLE();
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE);
LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE);
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
LED_C_ON();
cardSTATE = MFEMUL_WORK;
- if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED. sector=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
+ if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d",
+ cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B',
+ GetTickCount() - authTimer);
break;
}
case MFEMUL_SELECT2:{
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
if (!encrypted_data) { // first authentication
- if (MF_DBGLEVEL >= 2) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+ if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
crypto1_word(pcs, cuid ^ nonce, 0);//Update crypto state
num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce
} else { // nested authentication
- if (MF_DBGLEVEL >= 2) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+ if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
num_to_bytes(ans, 4, rAUTH_AT);
}
if(receivedCmd[0] == 0x30 // read block
|| receivedCmd[0] == 0xA0 // write block
- || receivedCmd[0] == 0xC0
- || receivedCmd[0] == 0xC1
- || receivedCmd[0] == 0xC2 // inc dec restore
+ || receivedCmd[0] == 0xC0 // inc
+ || receivedCmd[0] == 0xC1 // dec
+ || receivedCmd[0] == 0xC2 // restore
|| receivedCmd[0] == 0xB0) { // transfer
if (receivedCmd[1] >= 16 * 4) {
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
}
// read block
if (receivedCmd[0] == 0x30) {
- if (MF_DBGLEVEL >= 2) {
+ if (MF_DBGLEVEL >= 4) {
Dbprintf("Reader reading block %d (0x%02x)",receivedCmd[1],receivedCmd[1]);
}
emlGetMem(response, receivedCmd[1], 1);
}
// write block
if (receivedCmd[0] == 0xA0) {
- if (MF_DBGLEVEL >= 2) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd[1],receivedCmd[1]);
+ if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd[1],receivedCmd[1]);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
cardSTATE = MFEMUL_WRITEBL2;
cardWRBL = receivedCmd[1];
}
// increment, decrement, restore
if (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2) {
- if (MF_DBGLEVEL >= 2) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+ if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
if (emlCheckValBl(receivedCmd[1])) {
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
}
// transfer
if (receivedCmd[0] == 0xB0) {
- if (MF_DBGLEVEL >= 2) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+ if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1]))
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
else
// C(red) A(yellow) B(green)
LEDsoff();
// init trace buffer
- iso14a_clear_trace();
+ iso14a_clear_trace();
+ iso14a_set_tracing(TRUE);
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.