]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge pull request #109 from pwpiwi/image_shrink
authorpwpiwi <pwpiwi@users.noreply.github.com>
Wed, 24 Jun 2015 05:47:45 +0000 (07:47 +0200)
committerpwpiwi <pwpiwi@users.noreply.github.com>
Wed, 24 Jun 2015 05:47:45 +0000 (07:47 +0200)
Compress FPGA configs and initialized data

47 files changed:
CHANGELOG.md
COMPILING.txt
armsrc/Makefile
armsrc/aes.c
armsrc/appmain.c
armsrc/apps.h
armsrc/epa.c
armsrc/epa.h
armsrc/iso14443.c [deleted file]
armsrc/iso14443a.c
armsrc/iso14443b.c [new file with mode: 0644]
armsrc/lfops.c
armsrc/mifarecmd.c
armsrc/mifareutil.c
armsrc/mifareutil.h
armsrc/optimized_cipher.c
client/Makefile
client/cmddata.c
client/cmddata.h
client/cmdhf.c
client/cmdhf14b.c
client/cmdhfepa.c
client/cmdhfmf.c
client/cmdhfmfu.c
client/cmdhfmfu.h
client/cmdlf.c
client/cmdlfem4x.c
client/cmdlft55xx.c
client/hid-flasher/usb_cmd.h
client/lualibs/commands.lua
client/lualibs/utils.lua
client/scripting.c
client/scripts/didump.lua [new file with mode: 0644]
client/scripts/dumptoemul.lua
client/util.c
client/util.h
common/crc16.c
common/crc16.h
common/lfdemod.c
common/lfdemod.h
common/protocols.c
common/sha1.c [new file with mode: 0644]
common/sha1.h [new file with mode: 0644]
fpga/fpga_hf.bit
fpga/fpga_hf.v
fpga/hi_read_rx_xcorr.v
include/usb_cmd.h

index 85e7f91527753d1443066bed07527383b18c5b2c..b416e26a6c194bc7597f0ffc720ab26b10ff2356 100644 (file)
@@ -3,7 +3,20 @@ All notable changes to this project will be documented in this file.
 This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
 
 ## [Unreleased][unreleased]
+
+### Added
+- Add PACE replay functionality (frederikmoellers)
+
+### Fixed 
+- t55xx write timing (marshmellow)
+
+
+## [2.1.0][2015-06-23]
+
 ### Changed
+- Added ultralight/ntag tag type detection to `hf 14a read` (marshmellow)
+- Improved ultralight dump command to auto detect tag type, take authentication, and dump full memory (or subset specified) of known tag types (iceman1001 / marshmellow)
+- Combined ultralight read/write commands and added authentication (iceman1001)
 - Improved LF manchester and biphase demodulation and ask clock detection especially for reads with heavy clipping. (marshmellow)
 - Iclass read, `hf iclass read` now also reads tag config and prints configuration. (holiman)
 - *bootrom* needs to be flashed, due to new address boundaries between os and fpga, after a size optimization (piwi)
@@ -11,8 +24,12 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 ### Fixed
 - Fixed EM4x50 read/demod of the tags broadcasted memory blocks. 'lf em4x em4x50read' (not page read) (marshmellow)
 - Fixed issue #19, problems with LF T55xx commands (iceman1001, marshmellow)
+- Fixed various problems with iso14443b, issue #103 (piwi, marshmellow)
 
 ### Added
+- Added `hf search` - currently tests for 14443a tags, iclass tags, and 15693 tags (marshmellow) 
+- Added `hf mfu info` Ultralight/NTAG info command - reads tag configuration and info, allows authentication if needed (iceman1001, marshmellow)
+- Added Mifare Ultralight C and Ultralight EV1/NTAG authentication. (iceman1001)
 - Added changelog
 
 ## [2.0.0] - 2015-03-25
index c894f0ff04f14f6d9aa7d61e2502140ce50225b6..1cc34a0fc008309d1376b1755ceeb09e19c9ae3a 100644 (file)
@@ -81,7 +81,31 @@ Download the ProxSpace environment archive and extract it to C:\
 = Mac OS X =
 ============
 
-macport stuff should do ;)
+Tested on OSX 10.10 Yosemite
+
+1 - Install Xcode and Xcode Command Line Tools
+
+2 - Install Homebrew and dependencies
+    brew install readline
+    brew instal libusb
+
+3 - Download DevKitARM for OSX
+    http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
+    Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
+
+4 - Edit proxmark3/client/Makefile adding path to readline
+
+    LDLIBS = -L/usr/local/Cellar/readline/6.3.8/lib/ -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
+    CFLAGS = -std=c99 -I/usr/local/Cellar/readline/6.3.8/include/ -I. -I../include -I../common -I/opt/local/include -I../liblua  -Wall $(COMMON_FLAGS) -g -O4
+
+    Replace path /usr/local/Cellar/readline/6.3.8 with your actuall readline path. See homebrew manuals.
+
+5 - Set Environment
+
+    export DEVKITPRO=$HOME/proxmark3/
+    export DEVKITARM=$DEVKITPRO/devkitARM
+    export PATH=${PATH}:${DEVKITARM}/bin
+
 
 ============
 =   Linux  =
index 78d67934b1c2c9bd84915ef46ccdf69c083ca84b..f21f106ce097442477aebb7fd06414a2f8179b15 100644 (file)
@@ -18,7 +18,7 @@ APP_CFLAGS    = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_
 SRC_LF = lfops.c hitag2.c lfsampling.c
 SRC_ISO15693 = iso15693.c iso15693tools.c
 SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
-SRC_ISO14443b = iso14443.c
+SRC_ISO14443b = iso14443b.c
 SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c 
 SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
 
index 3df006bb355f2b0f7db494b36f98c8fd53355868..a199d04b7dc8d48bacbf446de619406385320159 100644 (file)
@@ -1,4 +1,3 @@
-#include "stdio.h"
 #include "aes.h"
 
 static const unsigned int Te0[256] = {
@@ -1138,6 +1137,9 @@ int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsig
 //////////////////////////////////////////////////////////////////////////////
 
 #ifndef EMBEDDED
+
+#include <stdio.h>
+
 int main()
 {
     AesCtx ctx;
index 263990468b3dbc06710a64bb5dc057c282a7918e..0cbfa2498e6ca7349f23766af663cd57ab70ac47 100644 (file)
@@ -250,55 +250,6 @@ void MeasureAntennaTuningHf(void)
 }
 
 
-void SimulateTagHfListen(void)
-{
-       // ToDo: historically this used the free buffer, which was 2744 Bytes long. 
-       // There might be a better size to be defined:
-       #define HF_14B_SNOOP_BUFFER_SIZE 2744
-       uint8_t *dest = BigBuf_malloc(HF_14B_SNOOP_BUFFER_SIZE);
-       uint8_t v = 0;
-       int i;
-       int p = 0;
-
-       // We're using this mode just so that I can test it out; the simulated
-       // tag mode would work just as well and be simpler.
-       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
-
-       // We need to listen to the high-frequency, peak-detected path.
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
-       FpgaSetupSsc();
-
-       i = 0;
-       for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0xff;
-               }
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                       uint8_t r = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
-                       v <<= 1;
-                       if(r & 1) {
-                               v |= 1;
-                       }
-                       p++;
-
-                       if(p >= 8) {
-                               dest[i] = v;
-                               v = 0;
-                               p = 0;
-                               i++;
-
-                               if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       DbpString("simulate tag (now type bitsamples)");
-}
-
 void ReadMem(int addr)
 {
        const uint8_t *data = ((uint8_t *)addr);
@@ -787,20 +738,17 @@ void UsbPacketReceived(uint8_t *packet, int len)
 #endif
 
 #ifdef WITH_ISO14443b
-               case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
-                       AcquireRawAdcSamplesIso14443(c->arg[0]);
-                       break;
                case CMD_READ_SRI512_TAG:
-                       ReadSTMemoryIso14443(0x0F);
+                       ReadSTMemoryIso14443b(0x0F);
                        break;
                case CMD_READ_SRIX4K_TAG:
-                       ReadSTMemoryIso14443(0x7F);
+                       ReadSTMemoryIso14443b(0x7F);
                        break;
-               case CMD_SNOOP_ISO_14443:
-                       SnoopIso14443();
+               case CMD_SNOOP_ISO_14443B:
+                       SnoopIso14443b();
                        break;
-               case CMD_SIMULATE_TAG_ISO_14443:
-                       SimulateIso14443Tag();
+               case CMD_SIMULATE_TAG_ISO_14443B:
+                       SimulateIso14443bTag();
                        break;
                case CMD_ISO_14443B_COMMAND:
                        SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
@@ -821,6 +769,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
                case CMD_EPA_PACE_COLLECT_NONCE:
                        EPA_PACE_Collect_Nonce(c);
                        break;
+               case CMD_EPA_PACE_REPLAY:
+                       EPA_PACE_Replay(c);
+                       break;
                        
                case CMD_READER_MIFARE:
                        ReaderMifare(c->arg[0]);
@@ -846,11 +797,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
                case CMD_MIFARE_WRITEBL:
                        MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
-               case CMD_MIFAREU_WRITEBL_COMPAT:
-                       MifareUWriteBlock(c->arg[0], c->d.asBytes);
-                       break;
+               //case CMD_MIFAREU_WRITEBL_COMPAT:
+                       //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
+                       //break;
                case CMD_MIFAREU_WRITEBL:
-                       MifareUWriteBlock_Special(c->arg[0], c->d.asBytes);
+                       MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes);
                        break;
                case CMD_MIFARE_NESTED:
                        MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
@@ -916,10 +867,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        break;
 #endif
 
-               case CMD_SIMULATE_TAG_HF_LISTEN:
-                       SimulateTagHfListen();
-                       break;
-
                case CMD_BUFF_CLEAR:
                        BigBuf_Clear();
                        break;
index 98be05a3c07b6355802a0379328978cdbef687e8..bb094b330521b08efbe4b57ff9fa8ee70fd8c250 100644 (file)
@@ -88,10 +88,10 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
 void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
 
 /// iso14443.h
-void SimulateIso14443Tag(void);
-void AcquireRawAdcSamplesIso14443(uint32_t parameter);
-void ReadSTMemoryIso14443(uint32_t);
-void RAMFUNC SnoopIso14443(void);
+void SimulateIso14443bTag(void);
+void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
+void ReadSTMemoryIso14443b(uint32_t);
+void RAMFUNC SnoopIso14443b(void);
 void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
 
 /// iso14443a.h
@@ -107,6 +107,7 @@ void RAMFUNC SniffMifare(uint8_t param);
 
 /// epa.h
 void EPA_PACE_Collect_Nonce(UsbCommand * c);
+void EPA_PACE_Replay(UsbCommand *c);
 
 // mifarecmd.h
 void ReaderMifare(bool first_try);
@@ -117,8 +118,8 @@ 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 MifareUWriteBlock(uint8_t arg0,uint8_t *datain);
-void MifareUWriteBlock_Special(uint8_t arg0,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 MifareChkKeys(uint8_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);
index 0006d59d01c03fd4944caefef829771b1b8068fc..6bd8692ecaa52d53c7c18ea3364acac26fdb670a 100644 (file)
@@ -5,7 +5,7 @@
 // at your option, any later version. See the LICENSE.txt file for the text of
 // the license.
 //-----------------------------------------------------------------------------
-// Routines to support the German eletronic "Personalausweis" (ID card)
+// Routines to support the German electronic "Personalausweis" (ID card)
 // Note that the functions which do not implement USB commands do NOT initialize
 // the card (with iso14443a_select_card etc.). If You want to use these
 // functions, You need to do the setup before calling them!
@@ -74,6 +74,32 @@ static const uint8_t oid_pace_start[] = {
     0x04 // id-PACE
 };
 
+// APDUs for replaying:
+// MSE: Set AT (initiate PACE)
+static uint8_t apdu_replay_mse_set_at_pace[41];
+// General Authenticate (Get Nonce)
+static uint8_t apdu_replay_general_authenticate_pace_get_nonce[8];
+// General Authenticate (Map Nonce)
+static uint8_t apdu_replay_general_authenticate_pace_map_nonce[75];
+// General Authenticate (Mutual Authenticate)
+static uint8_t apdu_replay_general_authenticate_pace_mutual_authenticate[75];
+// General Authenticate (Perform Key Agreement)
+static uint8_t apdu_replay_general_authenticate_pace_perform_key_agreement[18];
+// pointers to the APDUs (for iterations)
+static struct {
+       uint8_t len;
+       uint8_t *data;
+} const apdus_replay[] = {
+       {sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace},
+       {sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce},
+       {sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce},
+       {sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate},
+       {sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement}
+};
+
+// lengths of the replay APDUs
+static uint8_t apdu_lengths_replay[5];
+
 //-----------------------------------------------------------------------------
 // Closes the communication channel and turns off the field
 //-----------------------------------------------------------------------------
@@ -101,7 +127,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
                             pace_version_info_t *pace_info)
 {
        size_t index = 0;
-       
+
        while (index <= length - 2) {
                // determine type of element
                // SET or SEQUENCE
@@ -158,7 +184,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
                        index += 2 + data[index + 1];
                }
        }
-       
+
        // TODO: We should check whether we reached the end in error, but for that
        //       we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO)
        return 0;
@@ -176,7 +202,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
        // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
        uint8_t response_apdu[262];
        int rapdu_length = 0;
-       
+
        // select the file EF.CardAccess
        rapdu_length = iso14_apdu((uint8_t *)apdu_select_binary_cardaccess,
                                  sizeof(apdu_select_binary_cardaccess),
@@ -188,7 +214,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
                Dbprintf("epa - no select cardaccess");
                return -1;
        }
-       
+
        // read the file
        rapdu_length = iso14_apdu((uint8_t *)apdu_read_binary,
                                  sizeof(apdu_read_binary),
@@ -200,7 +226,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
                Dbprintf("epa - no read cardaccess");
                return -1;
        }
-       
+
        // copy the content into the buffer
        // length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
        size_t to_copy = rapdu_length - 6;
@@ -215,16 +241,11 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
 //-----------------------------------------------------------------------------
 static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
 {
-//     // step in which the failure occured
-//     ack->arg[0] = step;
-//     // last return code
-//     ack->arg[1] = func_return;
-
        // power down the field
        EPA_Finish();
-       
+
        // send the USB packet
-  cmd_send(CMD_ACK,step,func_return,0,0,0);
+       cmd_send(CMD_ACK,step,func_return,0,0,0);
 }
 
 //-----------------------------------------------------------------------------
@@ -246,10 +267,6 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
        // return value of a function
        int func_return = 0;
 
-//     // initialize ack with 0s
-//     memset(ack->arg, 0, 12);
-//     memset(ack->d.asBytes, 0, 48);
-       
        // set up communication
        func_return = EPA_Setup();
        if (func_return != 0) {
@@ -277,11 +294,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
                EPA_PACE_Collect_Nonce_Abort(3, func_return);
                return;
        }
-       
+
        // initiate the PACE protocol
        // use the CAN for the password since that doesn't change
        func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
-       
+
        // now get the nonce
        uint8_t nonce[256] = {0};
        uint8_t requested_size = (uint8_t)c->arg[0];
@@ -292,14 +309,12 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
                EPA_PACE_Collect_Nonce_Abort(4, func_return);
                return;
        }
-  
-  // all done, return
+
+       // all done, return
        EPA_Finish();
-       
+
        // save received information
-//     ack->arg[1] = func_return;
-//     memcpy(ack->d.asBytes, nonce, func_return);
-  cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
+       cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
 }
 
 //-----------------------------------------------------------------------------
@@ -320,7 +335,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
               sizeof(apdu_general_authenticate_pace_get_nonce));
        // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
        apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
-       
+
        // send it
        uint8_t response_apdu[262];
        int send_return = iso14_apdu(apdu,
@@ -333,7 +348,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
        {
                return -1;
        }
-       
+
        // if there is no nonce in the RAPDU, return here
        if (send_return < 10)
        {
@@ -348,7 +363,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
        }
        // copy the nonce
        memcpy(nonce, response_apdu + 6, nonce_length);
-       
+
        return nonce_length;
 }
 
@@ -407,13 +422,79 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
        return 0;
 }
 
+//-----------------------------------------------------------------------------
+// Perform the PACE protocol by replaying given APDUs
+//-----------------------------------------------------------------------------
+void EPA_PACE_Replay(UsbCommand *c)
+{
+       uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
+
+       // if an APDU has been passed, save it
+       if (c->arg[0] != 0) {
+               // make sure it's not too big
+               if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
+               {
+                       cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
+               }
+               memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
+                  c->d.asBytes,
+                  c->arg[2]);
+               // save/update APDU length
+               if (c->arg[1] == 0) {
+                       apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];
+               } else {
+                       apdu_lengths_replay[c->arg[0] - 1] += c->arg[2];
+               }
+               cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
+               return;
+       }
+
+       // return value of a function
+       int func_return;
+
+       // set up communication
+       func_return = EPA_Setup();
+       if (func_return != 0) {
+               EPA_Finish();
+               cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0);
+               return;
+       }
+
+       // increase the timeout (at least some cards really do need this!)/////////////
+       // iso14a_set_timeout(0x0003FFFF);
+
+       // response APDU
+       uint8_t response_apdu[300] = {0};
+
+       // now replay the data and measure the timings
+       for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
+               StartCountUS();
+               func_return = iso14_apdu(apdus_replay[i].data,
+                                        apdu_lengths_replay[i],
+                                        response_apdu);
+               timings[i] = GetCountUS();
+               // every step but the last one should succeed
+               if (i < sizeof(apdu_lengths_replay) - 1
+                   && (func_return < 6
+                       || response_apdu[func_return - 4] != 0x90
+                       || response_apdu[func_return - 3] != 0x00))
+               {
+                       EPA_Finish();
+                       cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20);
+                       return;
+               }
+       }
+       EPA_Finish();
+       cmd_send(CMD_ACK,0,0,0,timings,20);
+       return;
+}
+
 //-----------------------------------------------------------------------------
 // Set up a communication channel (Card Select, PPS)
 // Returns 0 on success or a non-zero error code on failure
 //-----------------------------------------------------------------------------
 int EPA_Setup()
 {
-
        int return_code = 0;
        uint8_t uid[10];
        uint8_t pps_response[3];
@@ -422,20 +503,16 @@ 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);
        if (return_code != 1) {
-               Dbprintf("Epa: Can't select card");
                return 1;
        }
-
        // send the PPS request
        ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
        return_code = ReaderReceive(pps_response, pps_response_par);
        if (return_code != 3 || pps_response[0] != 0xD0) {
                return return_code == 0 ? 2 : return_code;
        }
-       
        return 0;
-}
\ No newline at end of file
+}
index 730652b79ef8b8afd31d0e20523dec6f83965ccf..0c580205da938c80d952a853af16c98cc140614d 100644 (file)
@@ -19,7 +19,7 @@ typedef struct {
        uint8_t parameter_id;
 } pace_version_info_t;
 
-// note: EPA_PACE_GetNonce is declared in apps.h
+// note: EPA_PACE_Collect_Nonce is declared in apps.h
 
 // general functions
 void EPA_Finish();
@@ -33,4 +33,4 @@ int EPA_Setup();
 int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password);
 int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce);
 
-#endif /* __EPA_H */
\ No newline at end of file
+#endif /* __EPA_H */
diff --git a/armsrc/iso14443.c b/armsrc/iso14443.c
deleted file mode 100644 (file)
index c7f49f1..0000000
+++ /dev/null
@@ -1,1250 +0,0 @@
-//-----------------------------------------------------------------------------
-// Jonathan Westhues, split Nov 2006
-//
-// 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.
-//-----------------------------------------------------------------------------
-// Routines to support ISO 14443. This includes both the reader software and
-// the `fake tag' modes. At the moment only the Type B modulation is
-// supported.
-//-----------------------------------------------------------------------------
-
-#include "proxmark3.h"
-#include "apps.h"
-#include "util.h"
-#include "string.h"
-
-#include "iso14443crc.h"
-
-//static void GetSamplesFor14443(int weTx, int n);
-
-/*#define DEMOD_TRACE_SIZE 4096
-#define READER_TAG_BUFFER_SIZE 2048
-#define TAG_READER_BUFFER_SIZE 2048
-#define DEMOD_DMA_BUFFER_SIZE 1024
-*/
-//=============================================================================
-// An ISO 14443 Type B tag. We listen for commands from the reader, using
-// a UART kind of thing that's implemented in software. When we get a
-// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
-// If it's good, then we can do something appropriate with it, and send
-// a response.
-//=============================================================================
-
-//-----------------------------------------------------------------------------
-// Code up a string of octets at layer 2 (including CRC, we don't generate
-// that here) so that they can be transmitted to the reader. Doesn't transmit
-// them yet, just leaves them ready to send in ToSend[].
-//-----------------------------------------------------------------------------
-static void CodeIso14443bAsTag(const uint8_t *cmd, int len)
-{
-       int i;
-
-       ToSendReset();
-
-       // Transmit a burst of ones, as the initial thing that lets the
-       // reader get phase sync. This (TR1) must be > 80/fs, per spec,
-       // but tag that I've tried (a Paypass) exceeds that by a fair bit,
-       // so I will too.
-       for(i = 0; i < 20; i++) {
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-       }
-
-       // Send SOF.
-       for(i = 0; i < 10; i++) {
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-       }
-       for(i = 0; i < 2; i++) {
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-       }
-
-       for(i = 0; i < len; i++) {
-               int j;
-               uint8_t b = cmd[i];
-
-               // Start bit
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-
-               // Data bits
-               for(j = 0; j < 8; j++) {
-                       if(b & 1) {
-                               ToSendStuffBit(1);
-                               ToSendStuffBit(1);
-                               ToSendStuffBit(1);
-                               ToSendStuffBit(1);
-                       } else {
-                               ToSendStuffBit(0);
-                               ToSendStuffBit(0);
-                               ToSendStuffBit(0);
-                               ToSendStuffBit(0);
-                       }
-                       b >>= 1;
-               }
-
-               // Stop bit
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-       }
-
-       // Send SOF.
-       for(i = 0; i < 10; i++) {
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-               ToSendStuffBit(0);
-       }
-       for(i = 0; i < 10; i++) {
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-       }
-
-       // Convert from last byte pos to length
-       ToSendMax++;
-
-       // Add a few more for slop
-       ToSendMax += 2;
-}
-
-//-----------------------------------------------------------------------------
-// The software UART that receives commands from the reader, and its state
-// variables.
-//-----------------------------------------------------------------------------
-static struct {
-       enum {
-               STATE_UNSYNCD,
-               STATE_GOT_FALLING_EDGE_OF_SOF,
-               STATE_AWAITING_START_BIT,
-               STATE_RECEIVING_DATA,
-               STATE_ERROR_WAIT
-       }       state;
-       uint16_t    shiftReg;
-       int     bitCnt;
-       int     byteCnt;
-       int     byteCntMax;
-       int     posCnt;
-       uint8_t   *output;
-} Uart;
-
-/* Receive & handle a bit coming from the reader.
- *
- * LED handling:
- * LED A -> ON once we have received the SOF and are expecting the rest.
- * LED A -> OFF once we have received EOF or are in error state or unsynced
- *
- * Returns: true if we received a EOF
- *          false if we are still waiting for some more
- */
-static int Handle14443UartBit(int bit)
-{
-       switch(Uart.state) {
-               case STATE_UNSYNCD:
-                       LED_A_OFF();
-                       if(!bit) {
-                               // we went low, so this could be the beginning
-                               // of an SOF
-                               Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
-                               Uart.posCnt = 0;
-                               Uart.bitCnt = 0;
-                       }
-                       break;
-
-               case STATE_GOT_FALLING_EDGE_OF_SOF:
-                       Uart.posCnt++;
-                       if(Uart.posCnt == 2) {
-                               if(bit) {
-                                       if(Uart.bitCnt >= 10) {
-                                               // we've seen enough consecutive
-                                               // zeros that it's a valid SOF
-                                               Uart.posCnt = 0;
-                                               Uart.byteCnt = 0;
-                                               Uart.state = STATE_AWAITING_START_BIT;
-                                               LED_A_ON(); // Indicate we got a valid SOF
-                                       } else {
-                                               // didn't stay down long enough
-                                               // before going high, error
-                                               Uart.state = STATE_ERROR_WAIT;
-                                       }
-                               } else {
-                                       // do nothing, keep waiting
-                               }
-                               Uart.bitCnt++;
-                       }
-                       if(Uart.posCnt >= 4) Uart.posCnt = 0;
-                       if(Uart.bitCnt > 14) {
-                               // Give up if we see too many zeros without
-                               // a one, too.
-                               Uart.state = STATE_ERROR_WAIT;
-                       }
-                       break;
-
-               case STATE_AWAITING_START_BIT:
-                       Uart.posCnt++;
-                       if(bit) {
-                               if(Uart.posCnt > 25) {
-                                       // stayed high for too long between
-                                       // characters, error
-                                       Uart.state = STATE_ERROR_WAIT;
-                               }
-                       } else {
-                               // falling edge, this starts the data byte
-                               Uart.posCnt = 0;
-                               Uart.bitCnt = 0;
-                               Uart.shiftReg = 0;
-                               Uart.state = STATE_RECEIVING_DATA;
-                               LED_A_ON(); // Indicate we're receiving
-                       }
-                       break;
-
-               case STATE_RECEIVING_DATA:
-                       Uart.posCnt++;
-                       if(Uart.posCnt == 2) {
-                               // time to sample a bit
-                               Uart.shiftReg >>= 1;
-                               if(bit) {
-                                       Uart.shiftReg |= 0x200;
-                               }
-                               Uart.bitCnt++;
-                       }
-                       if(Uart.posCnt >= 4) {
-                               Uart.posCnt = 0;
-                       }
-                       if(Uart.bitCnt == 10) {
-                               if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
-                               {
-                                       // this is a data byte, with correct
-                                       // start and stop bits
-                                       Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
-                                       Uart.byteCnt++;
-
-                                       if(Uart.byteCnt >= Uart.byteCntMax) {
-                                               // Buffer overflowed, give up
-                                               Uart.posCnt = 0;
-                                               Uart.state = STATE_ERROR_WAIT;
-                                       } else {
-                                               // so get the next byte now
-                                               Uart.posCnt = 0;
-                                               Uart.state = STATE_AWAITING_START_BIT;
-                                       }
-                               } else if(Uart.shiftReg == 0x000) {
-                                       // this is an EOF byte
-                                       LED_A_OFF(); // Finished receiving
-                                       return TRUE;
-                               } else {
-                                       // this is an error
-                                       Uart.posCnt = 0;
-                                       Uart.state = STATE_ERROR_WAIT;
-                               }
-                       }
-                       break;
-
-               case STATE_ERROR_WAIT:
-                       // We're all screwed up, so wait a little while
-                       // for whatever went wrong to finish, and then
-                       // start over.
-                       Uart.posCnt++;
-                       if(Uart.posCnt > 10) {
-                               Uart.state = STATE_UNSYNCD;
-                       }
-                       break;
-
-               default:
-                       Uart.state = STATE_UNSYNCD;
-                       break;
-       }
-
-       // This row make the error blew circular buffer in hf 14b snoop
-       //if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error
-
-       return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// Receive a command (from the reader to us, where we are the simulated tag),
-// and store it in the given buffer, up to the given maximum length. Keeps
-// spinning, waiting for a well-framed command, until either we get one
-// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
-//
-// Assume that we're called with the SSC (to the FPGA) and ADC path set
-// correctly.
-//-----------------------------------------------------------------------------
-static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen)
-{
-       uint8_t mask;
-       int i, bit;
-
-       // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
-       // only, since we are receiving, not transmitting).
-       // Signal field is off with the appropriate LED
-       LED_D_OFF();
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
-
-
-       // Now run a `software UART' on the stream of incoming samples.
-       Uart.output = received;
-       Uart.byteCntMax = maxLen;
-       Uart.state = STATE_UNSYNCD;
-
-       for(;;) {
-               WDT_HIT();
-
-               if(BUTTON_PRESS()) return FALSE;
-
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0x00;
-               }
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                       uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-
-                       mask = 0x80;
-                       for(i = 0; i < 8; i++, mask >>= 1) {
-                               bit = (b & mask);
-                               if(Handle14443UartBit(bit)) {
-                                       *len = Uart.byteCnt;
-                                       return TRUE;
-                               }
-                       }
-               }
-       }
-}
-
-//-----------------------------------------------------------------------------
-// Main loop of simulated tag: receive commands from reader, decide what
-// response to send, and send it.
-//-----------------------------------------------------------------------------
-void SimulateIso14443Tag(void)
-{
-       static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
-       static const uint8_t response1[] = {
-               0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,
-               0x00, 0x21, 0x85, 0x5e, 0xd7
-       };
-
-       uint8_t *resp;
-       int respLen;
-
-       uint8_t *resp1 = BigBuf_get_addr() + 800;
-       int resp1Len;
-
-       uint8_t *receivedCmd = BigBuf_get_addr();
-       int len;
-
-       int i;
-
-       int cmdsRecvd = 0;
-
-       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-       memset(receivedCmd, 0x44, 400);
-
-       CodeIso14443bAsTag(response1, sizeof(response1));
-       memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
-
-       // We need to listen to the high-frequency, peak-detected path.
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-       FpgaSetupSsc();
-
-       cmdsRecvd = 0;
-
-       for(;;) {
-               uint8_t b1, b2;
-
-               if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {
-               Dbprintf("button pressed, received %d commands", cmdsRecvd);
-               break;
-               }
-
-               // Good, look at the command now.
-
-               if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {
-                       resp = resp1; respLen = resp1Len;
-               } else {
-                       Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);
-                       // And print whether the CRC fails, just for good measure
-                       ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);
-                       if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {
-                               // Not so good, try again.
-                               DbpString("+++CRC fail");
-                       } else {
-                               DbpString("CRC passes");
-                       }
-                       break;
-               }
-
-               memset(receivedCmd, 0x44, 32);
-
-               cmdsRecvd++;
-
-               if(cmdsRecvd > 0x30) {
-                       DbpString("many commands later...");
-                       break;
-               }
-
-               if(respLen <= 0) continue;
-
-               // Modulate BPSK
-               // Signal field is off with the appropriate LED
-               LED_D_OFF();
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
-               AT91C_BASE_SSC->SSC_THR = 0xff;
-               FpgaSetupSsc();
-
-               // Transmit the response.
-               i = 0;
-               for(;;) {
-                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                               uint8_t b = resp[i];
-
-                               AT91C_BASE_SSC->SSC_THR = b;
-
-                               i++;
-                               if(i > respLen) {
-                                       break;
-                               }
-                       }
-                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                               volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-                               (void)b;
-                       }
-               }
-       }
-}
-
-//=============================================================================
-// An ISO 14443 Type B reader. We take layer two commands, code them
-// appropriately, and then send them to the tag. We then listen for the
-// tag's response, which we leave in the buffer to be demodulated on the
-// PC side.
-//=============================================================================
-
-static struct {
-       enum {
-               DEMOD_UNSYNCD,
-               DEMOD_PHASE_REF_TRAINING,
-               DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
-               DEMOD_GOT_FALLING_EDGE_OF_SOF,
-               DEMOD_AWAITING_START_BIT,
-               DEMOD_RECEIVING_DATA,
-               DEMOD_ERROR_WAIT
-       }       state;
-       int     bitCount;
-       int     posCount;
-       int     thisBit;
-       int     metric;
-       int     metricN;
-       uint16_t    shiftReg;
-       uint8_t   *output;
-       int     len;
-       int     sumI;
-       int     sumQ;
-} Demod;
-
-/*
- * Handles reception of a bit from the tag
- *
- * LED handling:
- * LED C -> ON once we have received the SOF and are expecting the rest.
- * LED C -> OFF once we have received EOF or are unsynced
- *
- * Returns: true if we received a EOF
- *          false if we are still waiting for some more
- *
- */
-static RAMFUNC int Handle14443SamplesDemod(int ci, int cq)
-{
-       int v;
-
-       // The soft decision on the bit uses an estimate of just the
-       // quadrant of the reference angle, not the exact angle.
-#define MAKE_SOFT_DECISION() { \
-               if(Demod.sumI > 0) { \
-                       v = ci; \
-               } else { \
-                       v = -ci; \
-               } \
-               if(Demod.sumQ > 0) { \
-                       v += cq; \
-               } else { \
-                       v -= cq; \
-               } \
-       }
-
-       switch(Demod.state) {
-               case DEMOD_UNSYNCD:
-                       v = ci;
-                       if(v < 0) v = -v;
-                       if(cq > 0) {
-                               v += cq;
-                       } else {
-                               v -= cq;
-                       }
-                       if(v > 40) {
-                               Demod.posCount = 0;
-                               Demod.state = DEMOD_PHASE_REF_TRAINING;
-                               Demod.sumI = 0;
-                               Demod.sumQ = 0;
-                       }
-                       break;
-
-               case DEMOD_PHASE_REF_TRAINING:
-                       if(Demod.posCount < 8) {
-                               Demod.sumI += ci;
-                               Demod.sumQ += cq;
-                       } else if(Demod.posCount > 100) {
-                               // error, waited too long
-                               Demod.state = DEMOD_UNSYNCD;
-                       } else {
-                               MAKE_SOFT_DECISION();
-                               if(v < 0) {
-                                       Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
-                                       Demod.posCount = 0;
-                               }
-                       }
-                       Demod.posCount++;
-                       break;
-
-               case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
-                       MAKE_SOFT_DECISION();
-                       if(v < 0) {
-                               Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
-                               Demod.posCount = 0;
-                       } else {
-                               if(Demod.posCount > 100) {
-                                       Demod.state = DEMOD_UNSYNCD;
-                               }
-                       }
-                       Demod.posCount++;
-                       break;
-
-               case DEMOD_GOT_FALLING_EDGE_OF_SOF:
-                       MAKE_SOFT_DECISION();
-                       if(v > 0) {
-                               if(Demod.posCount < 12) {
-                                       Demod.state = DEMOD_UNSYNCD;
-                               } else {
-                                       LED_C_ON(); // Got SOF
-                                       Demod.state = DEMOD_AWAITING_START_BIT;
-                                       Demod.posCount = 0;
-                                       Demod.len = 0;
-                                       Demod.metricN = 0;
-                                       Demod.metric = 0;
-                               }
-                       } else {
-                               if(Demod.posCount > 100) {
-                                       Demod.state = DEMOD_UNSYNCD;
-                               }
-                       }
-                       Demod.posCount++;
-                       break;
-
-               case DEMOD_AWAITING_START_BIT:
-                       MAKE_SOFT_DECISION();
-                       if(v > 0) {
-                               if(Demod.posCount > 10) {
-                                       Demod.state = DEMOD_UNSYNCD;
-                               }
-                       } else {
-                               Demod.bitCount = 0;
-                               Demod.posCount = 1;
-                               Demod.thisBit = v;
-                               Demod.shiftReg = 0;
-                               Demod.state = DEMOD_RECEIVING_DATA;
-                       }
-                       break;
-
-               case DEMOD_RECEIVING_DATA:
-                       MAKE_SOFT_DECISION();
-                       if(Demod.posCount == 0) {
-                               Demod.thisBit = v;
-                               Demod.posCount = 1;
-                       } else {
-                               Demod.thisBit += v;
-
-                               if(Demod.thisBit > 0) {
-                                       Demod.metric += Demod.thisBit;
-                               } else {
-                                       Demod.metric -= Demod.thisBit;
-                               }
-                               (Demod.metricN)++;
-
-                               Demod.shiftReg >>= 1;
-                               if(Demod.thisBit > 0) {
-                                       Demod.shiftReg |= 0x200;
-                               }
-
-                               Demod.bitCount++;
-                               if(Demod.bitCount == 10) {
-                                       uint16_t s = Demod.shiftReg;
-                                       if((s & 0x200) && !(s & 0x001)) {
-                                               uint8_t b = (s >> 1);
-                                               Demod.output[Demod.len] = b;
-                                               Demod.len++;
-                                               Demod.state = DEMOD_AWAITING_START_BIT;
-                                       } else if(s == 0x000) {
-                                               // This is EOF
-                                               LED_C_OFF();
-                                               Demod.state = DEMOD_UNSYNCD;
-                                               return TRUE;
-                                       } else {
-                                               Demod.state = DEMOD_UNSYNCD;
-                                       }
-                               }
-                               Demod.posCount = 0;
-                       }
-                       break;
-
-               default:
-                       Demod.state = DEMOD_UNSYNCD;
-                       break;
-       }
-
-       if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...
-       return FALSE;
-}
-static void DemodReset()
-{
-       // Clear out the state of the "UART" that receives from the tag.
-       Demod.len = 0;
-       Demod.state = DEMOD_UNSYNCD;
-       memset(Demod.output, 0x00, MAX_FRAME_SIZE);
-}
-static void DemodInit(uint8_t *data)
-{
-       Demod.output = data;
-       DemodReset();
-}
-
-static void UartReset()
-{
-       Uart.byteCntMax = MAX_FRAME_SIZE;
-       Uart.state = STATE_UNSYNCD;
-       Uart.byteCnt = 0;
-       Uart.bitCnt = 0;
-}
-static void UartInit(uint8_t *data)
-{
-       Uart.output = data;
-       UartReset();
-}
-
-/*
- *  Demodulate the samples we received from the tag, also log to tracebuffer
- *  weTx: set to 'TRUE' if we behave like a reader
- *        set to 'FALSE' if we behave like a snooper
- *  quiet: set to 'TRUE' to disable debug output
- */
-static void GetSamplesFor14443Demod(int weTx, int n, int quiet)
-{
-       int max = 0;
-       int gotFrame = FALSE;
-       int lastRxCounter, ci, cq, samples = 0;
-
-       // Allocate memory from BigBuf for some buffers
-       // free all previous allocations first
-       BigBuf_free();
-       
-       // The command (reader -> tag) that we're receiving.
-       uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
-       
-       // The response (tag -> reader) that we're receiving.
-       uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
-       
-       // The DMA buffer, used to stream samples from the FPGA
-       uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
-
-       // Set up the demodulator for tag -> reader responses.
-       DemodInit(receivedResponse);
-       // Set up the demodulator for the reader -> tag commands
-       UartInit(receivedCmd);
-
-       // Setup and start DMA.
-       FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE);
-
-       uint8_t *upTo= dmaBuf;
-       lastRxCounter = DMA_BUFFER_SIZE;
-
-       // Signal field is ON with the appropriate LED:
-       if (weTx) LED_D_ON(); else LED_D_OFF();
-       // And put the FPGA in the appropriate mode
-       FpgaWriteConfWord(
-               FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
-               (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
-
-       for(;;) {
-               int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
-               if(behindBy > max) max = behindBy;
-
-               while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1))
-                                       > 2)
-               {
-                       ci = upTo[0];
-                       cq = upTo[1];
-                       upTo += 2;
-                       if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
-                               upTo -= DMA_BUFFER_SIZE;
-                               AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
-                               AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
-                       }
-                       lastRxCounter -= 2;
-                       if(lastRxCounter <= 0) {
-                               lastRxCounter += DMA_BUFFER_SIZE;
-                       }
-
-                       samples += 2;
-
-                       Handle14443UartBit(1);
-                       Handle14443UartBit(1);
-
-                       if(Handle14443SamplesDemod(ci, cq)) {
-                               gotFrame = 1;
-                       }
-               }
-
-               if(samples > 2000) {
-                       break;
-               }
-       }
-       AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
-       if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len);
-       //Tracing
-       if (tracing && Demod.len > 0) {
-               uint8_t parity[MAX_PARITY_SIZE];
-               GetParity(Demod.output , Demod.len, parity);
-               LogTrace(Demod.output,Demod.len, 0, 0, parity, FALSE);
-       }
-}
-
-//-----------------------------------------------------------------------------
-// Read the tag's response. We just receive a stream of slightly-processed
-// samples from the FPGA, which we will later do some signal processing on,
-// to get the bits.
-//-----------------------------------------------------------------------------
-/*static void GetSamplesFor14443(int weTx, int n)
-{
-       uint8_t *dest = (uint8_t *)BigBuf;
-       int c;
-
-       FpgaWriteConfWord(
-               FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
-               (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
-
-       c = 0;
-       for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0x43;
-               }
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                       int8_t b;
-                       b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
-
-                       dest[c++] = (uint8_t)b;
-
-                       if(c >= n) {
-                               break;
-                       }
-               }
-       }
-}*/
-
-//-----------------------------------------------------------------------------
-// Transmit the command (to the tag) that was placed in ToSend[].
-//-----------------------------------------------------------------------------
-static void TransmitFor14443(void)
-{
-       int c;
-
-       FpgaSetupSsc();
-
-       while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-               AT91C_BASE_SSC->SSC_THR = 0xff;
-       }
-
-       // Signal field is ON with the appropriate Red LED
-       LED_D_ON();
-       // Signal we are transmitting with the Green LED
-       LED_B_ON();
-       FpgaWriteConfWord(
-               FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
-
-       for(c = 0; c < 10;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0xff;
-                       c++;
-               }
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
-                       (void)r;
-               }
-               WDT_HIT();
-       }
-
-       c = 0;
-       for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = ToSend[c];
-                       c++;
-                       if(c >= ToSendMax) {
-                               break;
-                       }
-               }
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
-                       (void)r;
-               }
-               WDT_HIT();
-       }
-       LED_B_OFF(); // Finished sending
-}
-
-//-----------------------------------------------------------------------------
-// Code a layer 2 command (string of octets, including CRC) into ToSend[],
-// so that it is ready to transmit to the tag using TransmitFor14443().
-//-----------------------------------------------------------------------------
-static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
-{
-       int i, j;
-       uint8_t b;
-
-       ToSendReset();
-
-       // Establish initial reference level
-       for(i = 0; i < 40; i++) {
-               ToSendStuffBit(1);
-       }
-       // Send SOF
-       for(i = 0; i < 10; i++) {
-               ToSendStuffBit(0);
-       }
-
-       for(i = 0; i < len; i++) {
-               // Stop bits/EGT
-               ToSendStuffBit(1);
-               ToSendStuffBit(1);
-               // Start bit
-               ToSendStuffBit(0);
-               // Data bits
-               b = cmd[i];
-               for(j = 0; j < 8; j++) {
-                       if(b & 1) {
-                               ToSendStuffBit(1);
-                       } else {
-                               ToSendStuffBit(0);
-                       }
-                       b >>= 1;
-               }
-       }
-       // Send EOF
-       ToSendStuffBit(1);
-       for(i = 0; i < 10; i++) {
-               ToSendStuffBit(0);
-       }
-       for(i = 0; i < 8; i++) {
-               ToSendStuffBit(1);
-       }
-
-       // And then a little more, to make sure that the last character makes
-       // it out before we switch to rx mode.
-       for(i = 0; i < 24; i++) {
-               ToSendStuffBit(1);
-       }
-
-       // Convert from last character reference to length
-       ToSendMax++;
-}
-
-//-----------------------------------------------------------------------------
-// Read an ISO 14443 tag. We send it some set of commands, and record the
-// responses.
-// The command name is misleading, it actually decodes the reponse in HEX
-// into the output buffer (read the result using hexsamples, not hisamples)
-//
-// obsolete function only for test
-//-----------------------------------------------------------------------------
-void AcquireRawAdcSamplesIso14443(uint32_t parameter)
-{
-       uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
-
-       SendRawCommand14443B(sizeof(cmd1),1,1,cmd1);
-}
-
-/**
-  Convenience function to encode, transmit and trace iso 14443b comms
-  **/
-static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
-{
-       CodeIso14443bAsReader(cmd, len);
-       TransmitFor14443();
-       if (tracing) {
-               uint8_t parity[MAX_PARITY_SIZE];
-               GetParity(cmd, len, parity);
-               LogTrace(cmd,len, 0, 0, parity, TRUE);
-       }
-}
-
-//-----------------------------------------------------------------------------
-// Read a SRI512 ISO 14443 tag.
-//
-// SRI512 tags are just simple memory tags, here we're looking at making a dump
-// of the contents of the memory. No anticollision algorithm is done, we assume
-// we have a single tag in the field.
-//
-// I tried to be systematic and check every answer of the tag, every CRC, etc...
-//-----------------------------------------------------------------------------
-void ReadSTMemoryIso14443(uint32_t dwLast)
-{
-       clear_trace();
-       set_tracing(TRUE);
-
-       uint8_t i = 0x00;
-
-       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-       // Make sure that we start from off, since the tags are stateful;
-       // confusing things will happen if we don't reset them between reads.
-       LED_D_OFF();
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-       SpinDelay(200);
-
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-       FpgaSetupSsc();
-
-       // Now give it time to spin up.
-       // Signal field is on with the appropriate LED
-       LED_D_ON();
-       FpgaWriteConfWord(
-               FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
-       SpinDelay(200);
-
-       // First command: wake up the tag using the INITIATE command
-       uint8_t cmd1[] = { 0x06, 0x00, 0x97, 0x5b};
-
-       CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
-//    LED_A_ON();
-       GetSamplesFor14443Demod(TRUE, 2000,TRUE);
-//    LED_A_OFF();
-
-       if (Demod.len == 0) {
-       DbpString("No response from tag");
-       return;
-       } else {
-       Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x",
-               Demod.output[0], Demod.output[1],Demod.output[2]);
-       }
-       // There is a response, SELECT the uid
-       DbpString("Now SELECT tag:");
-       cmd1[0] = 0x0E; // 0x0E is SELECT
-       cmd1[1] = Demod.output[0];
-       ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
-       CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
-
-//    LED_A_ON();
-       GetSamplesFor14443Demod(TRUE, 2000,TRUE);
-//    LED_A_OFF();
-       if (Demod.len != 3) {
-       Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
-       return;
-       }
-       // Check the CRC of the answer:
-       ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
-       if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
-       DbpString("CRC Error reading select response.");
-       return;
-       }
-       // Check response from the tag: should be the same UID as the command we just sent:
-       if (cmd1[1] != Demod.output[0]) {
-       Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]);
-       return;
-       }
-       // Tag is now selected,
-       // First get the tag's UID:
-       cmd1[0] = 0x0B;
-       ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
-       CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
-
-//    LED_A_ON();
-       GetSamplesFor14443Demod(TRUE, 2000,TRUE);
-//    LED_A_OFF();
-       if (Demod.len != 10) {
-       Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
-       return;
-       }
-       // The check the CRC of the answer (use cmd1 as temporary variable):
-       ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);
-                  if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {
-       Dbprintf("CRC Error reading block! - Below: expected, got %x %x",
-               (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);
-       // Do not return;, let's go on... (we should retry, maybe ?)
-       }
-       Dbprintf("Tag UID (64 bits): %08x %08x",
-       (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],
-       (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
-
-       // Now loop to read all 16 blocks, address from 0 to last block
-       Dbprintf("Tag memory dump, block 0 to %d",dwLast);
-       cmd1[0] = 0x08;
-       i = 0x00;
-       dwLast++;
-       for (;;) {
-                  if (i == dwLast) {
-                       DbpString("System area block (0xff):");
-                       i = 0xff;
-               }
-               cmd1[1] = i;
-               ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
-               CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
-
-//         LED_A_ON();
-               GetSamplesFor14443Demod(TRUE, 2000,TRUE);
-//         LED_A_OFF();
-               if (Demod.len != 6) { // Check if we got an answer from the tag
-               DbpString("Expected 6 bytes from tag, got less...");
-               return;
-               }
-               // The check the CRC of the answer (use cmd1 as temporary variable):
-               ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);
-                       if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {
-               Dbprintf("CRC Error reading block! - Below: expected, got %x %x",
-                       (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);
-               // Do not return;, let's go on... (we should retry, maybe ?)
-               }
-               // Now print out the memory location:
-               Dbprintf("Address=%x, Contents=%x, CRC=%x", i,
-               (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
-               (Demod.output[4]<<8)+Demod.output[5]);
-               if (i == 0xff) {
-               break;
-               }
-               i++;
-       }
-}
-
-
-//=============================================================================
-// Finally, the `sniffer' combines elements from both the reader and
-// simulated tag, to show both sides of the conversation.
-//=============================================================================
-
-//-----------------------------------------------------------------------------
-// Record the sequence of commands sent by the reader to the tag, with
-// triggering so that we start recording at the point that the tag is moved
-// near the reader.
-//-----------------------------------------------------------------------------
-/*
- * Memory usage for this function, (within BigBuf)
- * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE
- * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE
- * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE
- * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DEMOD_DMA_BUFFER_SIZE
- */
-void RAMFUNC SnoopIso14443(void)
-{
-       // 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
-       // response from the tag.
-       int triggered = TRUE;
-
-       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-       BigBuf_free();
-
-       clear_trace();
-       set_tracing(TRUE);
-
-       // The DMA buffer, used to stream samples from the FPGA
-       uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
-       int lastRxCounter;
-       uint8_t *upTo;
-       int ci, cq;
-       int maxBehindBy = 0;
-
-       // Count of samples received so far, so that we can include timing
-       // information in the trace buffer.
-       int samples = 0;
-
-       DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
-       UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
-
-       // Print some debug information about the buffer sizes
-       Dbprintf("Snooping buffers initialized:");
-       Dbprintf("  Trace: %i bytes", BigBuf_max_traceLen());
-       Dbprintf("  Reader -> tag: %i bytes", MAX_FRAME_SIZE);
-       Dbprintf("  tag -> Reader: %i bytes", MAX_FRAME_SIZE);
-       Dbprintf("  DMA: %i bytes", DMA_BUFFER_SIZE);
-
-       // Signal field is off with the appropriate LED
-       LED_D_OFF();
-
-       // And put the FPGA in the appropriate mode
-       FpgaWriteConfWord(
-               FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
-               FPGA_HF_READER_RX_XCORR_SNOOP);
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-
-       // Setup for the DMA.
-       FpgaSetupSsc();
-       upTo = dmaBuf;
-       lastRxCounter = DMA_BUFFER_SIZE;
-       FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
-       uint8_t parity[MAX_PARITY_SIZE];
-       LED_A_ON();
-               
-       // And now we loop, receiving samples.
-       for(;;) {
-               int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
-                                                               (DMA_BUFFER_SIZE-1);
-               if(behindBy > maxBehindBy) {
-                       maxBehindBy = behindBy;
-                       if(behindBy > (9*DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
-                               Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
-                               break;
-                       }
-               }
-               if(behindBy < 2) continue;
-
-               ci = upTo[0];
-               cq = upTo[1];
-               upTo += 2;
-               lastRxCounter -= 2;
-               if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
-                       upTo -= DMA_BUFFER_SIZE;
-                       lastRxCounter += DMA_BUFFER_SIZE;
-                       AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
-                       AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
-               }
-
-               samples += 2;
-
-               if(Handle14443UartBit(ci & 1)) {
-                       if(triggered && tracing) {
-                               GetParity(Uart.output, Uart.byteCnt, parity);
-                               LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE);
-                       }
-                       if(Uart.byteCnt==0) Dbprintf("[1] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt);
-
-                       /* And ready to receive another command. */
-                       UartReset();
-                       /* And also reset the demod code, which might have been */
-                       /* false-triggered by the commands from the reader. */
-                       DemodReset();
-               }
-               if(Handle14443UartBit(cq & 1)) {
-                       if(triggered && tracing) {
-                               GetParity(Uart.output, Uart.byteCnt, parity);
-                               LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE);
-                       }
-                       if(Uart.byteCnt==0) Dbprintf("[2] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt);
-
-                       /* And ready to receive another command. */
-                       UartReset();
-                       /* And also reset the demod code, which might have been */
-                       /* false-triggered by the commands from the reader. */
-                       DemodReset();
-               }
-
-               if(Handle14443SamplesDemod(ci, cq)) {
-
-                       //Use samples as a time measurement
-                       if(tracing)
-                       {
-                               uint8_t parity[MAX_PARITY_SIZE];
-                               GetParity(Demod.output, Demod.len, parity);
-                               LogTrace(Demod.output,Demod.len,samples, samples,parity,FALSE);
-                       }
-                       triggered = TRUE;
-                       LED_A_OFF();
-                       LED_B_ON();
-
-                       // And ready to receive another response.
-                       DemodReset();
-               }
-               WDT_HIT();
-
-               if(!tracing) {
-                       DbpString("Reached trace limit");
-                       break;
-               }
-
-               if(BUTTON_PRESS()) {
-                       DbpString("cancelled");
-                       break;
-               }
-       }
-       FpgaDisableSscDma();
-       LED_A_OFF();
-       LED_B_OFF();
-       LED_C_OFF();
-       AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
-       DbpString("Snoop statistics:");
-       Dbprintf("  Max behind by: %i", maxBehindBy);
-       Dbprintf("  Uart State: %x", Uart.state);
-       Dbprintf("  Uart ByteCnt: %i", Uart.byteCnt);
-       Dbprintf("  Uart ByteCntMax: %i", Uart.byteCntMax);
-       Dbprintf("  Trace length: %i", BigBuf_get_traceLen());
-}
-
-/*
- * Send raw command to tag ISO14443B
- * @Input
- * datalen     len of buffer data
- * recv        bool when true wait for data from tag and send to client
- * powerfield  bool leave the field on when true
- * data        buffer with byte to send
- *
- * @Output
- * none
- *
- */
-
-void SendRawCommand14443B(uint32_t datalen, uint32_t recv,uint8_t powerfield, uint8_t data[])
-{
-       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
-       if(!powerfield)
-       {
-               // Make sure that we start from off, since the tags are stateful;
-               // confusing things will happen if we don't reset them between reads.
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-               LED_D_OFF();
-               SpinDelay(200);
-       }
-
-       if(!GETBIT(GPIO_LED_D))
-       {
-               SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-               FpgaSetupSsc();
-
-               // Now give it time to spin up.
-               // Signal field is on with the appropriate LED
-               LED_D_ON();
-               FpgaWriteConfWord(
-                       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
-               SpinDelay(200);
-       }
-
-       CodeAndTransmit14443bAsReader(data, datalen);
-
-       if(recv)
-       {
-               uint16_t iLen = MIN(Demod.len,USB_CMD_DATA_SIZE);
-               GetSamplesFor14443Demod(TRUE, 2000, TRUE);
-               cmd_send(CMD_ACK,iLen,0,0,Demod.output,iLen);
-       }
-       if(!powerfield)
-       {
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-               LED_D_OFF();
-       }
-}
-
index 64bbcbf50eaaa456123163bc16bd115a13e77ef2..cf64da2fbcdb3b8c3f6790cabac7429eef89d74f 100644 (file)
@@ -2510,13 +2510,13 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                                || receivedCmd[0] == 0xB0) { // transfer
                                        if (receivedCmd[1] >= 16 * 4) {
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
-                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
                                                break;
                                        }
 
                                        if (receivedCmd[1] / 4 != cardAUTHSC) {
                                                EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
-                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
                                                break;
                                        }
                                }
diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c
new file mode 100644 (file)
index 0000000..416c31f
--- /dev/null
@@ -0,0 +1,1218 @@
+//-----------------------------------------------------------------------------
+// Jonathan Westhues, split Nov 2006
+//
+// 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.
+//-----------------------------------------------------------------------------
+// Routines to support ISO 14443B. This includes both the reader software and
+// the `fake tag' modes.
+//-----------------------------------------------------------------------------
+
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#include "iso14443crc.h"
+
+#define RECEIVE_SAMPLES_TIMEOUT 2000
+#define ISO14443B_DMA_BUFFER_SIZE 256
+
+//=============================================================================
+// An ISO 14443 Type B tag. We listen for commands from the reader, using
+// a UART kind of thing that's implemented in software. When we get a
+// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
+// If it's good, then we can do something appropriate with it, and send
+// a response.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Code up a string of octets at layer 2 (including CRC, we don't generate
+// that here) so that they can be transmitted to the reader. Doesn't transmit
+// them yet, just leaves them ready to send in ToSend[].
+//-----------------------------------------------------------------------------
+static void CodeIso14443bAsTag(const uint8_t *cmd, int len)
+{
+       int i;
+
+       ToSendReset();
+
+       // Transmit a burst of ones, as the initial thing that lets the
+       // reader get phase sync. This (TR1) must be > 80/fs, per spec,
+       // but tag that I've tried (a Paypass) exceeds that by a fair bit,
+       // so I will too.
+       for(i = 0; i < 20; i++) {
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+       }
+
+       // Send SOF.
+       for(i = 0; i < 10; i++) {
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+       }
+       for(i = 0; i < 2; i++) {
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+       }
+
+       for(i = 0; i < len; i++) {
+               int j;
+               uint8_t b = cmd[i];
+
+               // Start bit
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+
+               // Data bits
+               for(j = 0; j < 8; j++) {
+                       if(b & 1) {
+                               ToSendStuffBit(1);
+                               ToSendStuffBit(1);
+                               ToSendStuffBit(1);
+                               ToSendStuffBit(1);
+                       } else {
+                               ToSendStuffBit(0);
+                               ToSendStuffBit(0);
+                               ToSendStuffBit(0);
+                               ToSendStuffBit(0);
+                       }
+                       b >>= 1;
+               }
+
+               // Stop bit
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+       }
+
+       // Send EOF.
+       for(i = 0; i < 10; i++) {
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+               ToSendStuffBit(0);
+       }
+       for(i = 0; i < 2; i++) {
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+       }
+
+       // Convert from last byte pos to length
+       ToSendMax++;
+}
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+       enum {
+               STATE_UNSYNCD,
+               STATE_GOT_FALLING_EDGE_OF_SOF,
+               STATE_AWAITING_START_BIT,
+               STATE_RECEIVING_DATA
+       }       state;
+       uint16_t    shiftReg;
+       int     bitCnt;
+       int     byteCnt;
+       int     byteCntMax;
+       int     posCnt;
+       uint8_t   *output;
+} Uart;
+
+/* Receive & handle a bit coming from the reader.
+ *
+ * This function is called 4 times per bit (every 2 subcarrier cycles).
+ * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us
+ *
+ * LED handling:
+ * LED A -> ON once we have received the SOF and are expecting the rest.
+ * LED A -> OFF once we have received EOF or are in error state or unsynced
+ *
+ * Returns: true if we received a EOF
+ *          false if we are still waiting for some more
+ */
+static RAMFUNC int Handle14443bUartBit(uint8_t bit)
+{
+       switch(Uart.state) {
+               case STATE_UNSYNCD:
+                       if(!bit) {
+                               // we went low, so this could be the beginning
+                               // of an SOF
+                               Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
+                               Uart.posCnt = 0;
+                               Uart.bitCnt = 0;
+                       }
+                       break;
+
+               case STATE_GOT_FALLING_EDGE_OF_SOF:
+                       Uart.posCnt++;
+                       if(Uart.posCnt == 2) {  // sample every 4 1/fs in the middle of a bit
+                               if(bit) {
+                                       if(Uart.bitCnt > 9) {
+                                               // we've seen enough consecutive
+                                               // zeros that it's a valid SOF
+                                               Uart.posCnt = 0;
+                                               Uart.byteCnt = 0;
+                                               Uart.state = STATE_AWAITING_START_BIT;
+                                               LED_A_ON(); // Indicate we got a valid SOF
+                                       } else {
+                                               // didn't stay down long enough
+                                               // before going high, error
+                                               Uart.state = STATE_UNSYNCD;
+                                       }
+                               } else {
+                                       // do nothing, keep waiting
+                               }
+                               Uart.bitCnt++;
+                       }
+                       if(Uart.posCnt >= 4) Uart.posCnt = 0;
+                       if(Uart.bitCnt > 12) {
+                               // Give up if we see too many zeros without
+                               // a one, too.
+                               LED_A_OFF();
+                               Uart.state = STATE_UNSYNCD;
+                       }
+                       break;
+
+               case STATE_AWAITING_START_BIT:
+                       Uart.posCnt++;
+                       if(bit) {
+                               if(Uart.posCnt > 50/2) {        // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
+                                       // stayed high for too long between
+                                       // characters, error
+                                       Uart.state = STATE_UNSYNCD;
+                               }
+                       } else {
+                               // falling edge, this starts the data byte
+                               Uart.posCnt = 0;
+                               Uart.bitCnt = 0;
+                               Uart.shiftReg = 0;
+                               Uart.state = STATE_RECEIVING_DATA;
+                       }
+                       break;
+
+               case STATE_RECEIVING_DATA:
+                       Uart.posCnt++;
+                       if(Uart.posCnt == 2) {
+                               // time to sample a bit
+                               Uart.shiftReg >>= 1;
+                               if(bit) {
+                                       Uart.shiftReg |= 0x200;
+                               }
+                               Uart.bitCnt++;
+                       }
+                       if(Uart.posCnt >= 4) {
+                               Uart.posCnt = 0;
+                       }
+                       if(Uart.bitCnt == 10) {
+                               if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
+                               {
+                                       // this is a data byte, with correct
+                                       // start and stop bits
+                                       Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
+                                       Uart.byteCnt++;
+
+                                       if(Uart.byteCnt >= Uart.byteCntMax) {
+                                               // Buffer overflowed, give up
+                                               LED_A_OFF();
+                                               Uart.state = STATE_UNSYNCD;
+                                       } else {
+                                               // so get the next byte now
+                                               Uart.posCnt = 0;
+                                               Uart.state = STATE_AWAITING_START_BIT;
+                                       }
+                               } else if (Uart.shiftReg == 0x000) {
+                                       // this is an EOF byte
+                                       LED_A_OFF(); // Finished receiving
+                                       Uart.state = STATE_UNSYNCD;
+                                       if (Uart.byteCnt != 0) {
+                                               return TRUE;
+                                       }
+                               } else {
+                                       // this is an error
+                                       LED_A_OFF();
+                                       Uart.state = STATE_UNSYNCD;
+                               }
+                       }
+                       break;
+
+               default:
+                       LED_A_OFF();
+                       Uart.state = STATE_UNSYNCD;
+                       break;
+       }
+
+       return FALSE;
+}
+
+
+static void UartReset()
+{
+       Uart.byteCntMax = MAX_FRAME_SIZE;
+       Uart.state = STATE_UNSYNCD;
+       Uart.byteCnt = 0;
+       Uart.bitCnt = 0;
+}
+
+
+static void UartInit(uint8_t *data)
+{
+       Uart.output = data;
+       UartReset();
+}
+
+
+//-----------------------------------------------------------------------------
+// Receive a command (from the reader to us, where we are the simulated tag),
+// and store it in the given buffer, up to the given maximum length. Keeps
+// spinning, waiting for a well-framed command, until either we get one
+// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
+//
+// Assume that we're called with the SSC (to the FPGA) and ADC path set
+// correctly.
+//-----------------------------------------------------------------------------
+static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len)
+{
+       // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen
+       // only, since we are receiving, not transmitting).
+       // Signal field is off with the appropriate LED
+       LED_D_OFF();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
+
+       // Now run a `software UART' on the stream of incoming samples.
+       UartInit(received);
+
+       for(;;) {
+               WDT_HIT();
+
+               if(BUTTON_PRESS()) return FALSE;
+
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+                       for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) {
+                               if(Handle14443bUartBit(b & mask)) {
+                                       *len = Uart.byteCnt;
+                                       return TRUE;
+                               }
+                       }
+               }
+       }
+       
+       return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// Main loop of simulated tag: receive commands from reader, decide what
+// response to send, and send it.
+//-----------------------------------------------------------------------------
+void SimulateIso14443bTag(void)
+{
+       // the only commands we understand is REQB, AFI=0, Select All, N=0:
+       static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
+       // ... and REQB, AFI=0, Normal Request, N=0:
+       static const uint8_t cmd2[] = { 0x05, 0x00, 0x00, 0x71, 0xFF };
+
+       // ... and we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922,
+       // supports only 106kBit/s in both directions, max frame size = 32Bytes,
+       // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported:
+       static const uint8_t response1[] = {
+               0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,
+               0x00, 0x21, 0x85, 0x5e, 0xd7
+       };
+
+       clear_trace();
+       set_tracing(TRUE);
+
+       const uint8_t *resp;
+       uint8_t *respCode;
+       uint16_t respLen, respCodeLen;
+
+       // allocate command receive buffer
+       BigBuf_free();
+       uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
+
+       uint16_t len;
+       uint16_t cmdsRecvd = 0;
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+
+       // prepare the (only one) tag answer:
+       CodeIso14443bAsTag(response1, sizeof(response1));
+       uint8_t *resp1Code = BigBuf_malloc(ToSendMax);
+       memcpy(resp1Code, ToSend, ToSendMax); 
+       uint16_t resp1CodeLen = ToSendMax;
+
+       // We need to listen to the high-frequency, peak-detected path.
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+       FpgaSetupSsc();
+
+       cmdsRecvd = 0;
+
+       for(;;) {
+
+               if(!GetIso14443bCommandFromReader(receivedCmd, &len)) {
+                       Dbprintf("button pressed, received %d commands", cmdsRecvd);
+                       break;
+               }
+
+               if (tracing) {
+                       uint8_t parity[MAX_PARITY_SIZE];
+                       LogTrace(receivedCmd, len, 0, 0, parity, TRUE);
+               }
+
+               // Good, look at the command now.
+               if ( (len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0)
+                       || (len == sizeof(cmd2) && memcmp(receivedCmd, cmd2, len) == 0) ) {
+                       resp = response1; 
+                       respLen = sizeof(response1);
+                       respCode = resp1Code; 
+                       respCodeLen = resp1CodeLen;
+               } else {
+                       Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);
+                       // And print whether the CRC fails, just for good measure
+                       uint8_t b1, b2;
+                       ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);
+                       if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {
+                               // Not so good, try again.
+                               DbpString("+++CRC fail");
+                       } else {
+                               DbpString("CRC passes");
+                       }
+                       break;
+               }
+
+               cmdsRecvd++;
+
+               if(cmdsRecvd > 0x30) {
+                       DbpString("many commands later...");
+                       break;
+               }
+
+               if(respCodeLen <= 0) continue;
+
+               // Modulate BPSK
+               // Signal field is off with the appropriate LED
+               LED_D_OFF();
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
+               AT91C_BASE_SSC->SSC_THR = 0xff;
+               FpgaSetupSsc();
+
+               // Transmit the response.
+               uint16_t i = 0;
+               for(;;) {
+                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                               uint8_t b = respCode[i];
+
+                               AT91C_BASE_SSC->SSC_THR = b;
+
+                               i++;
+                               if(i > respCodeLen) {
+                                       break;
+                               }
+                       }
+                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                               volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+                               (void)b;
+                       }
+               }
+               
+               // trace the response:
+               if (tracing) {
+                       uint8_t parity[MAX_PARITY_SIZE];
+                       LogTrace(resp, respLen, 0, 0, parity, FALSE);
+               }
+                       
+       }
+}
+
+//=============================================================================
+// An ISO 14443 Type B reader. We take layer two commands, code them
+// appropriately, and then send them to the tag. We then listen for the
+// tag's response, which we leave in the buffer to be demodulated on the
+// PC side.
+//=============================================================================
+
+static struct {
+       enum {
+               DEMOD_UNSYNCD,
+               DEMOD_PHASE_REF_TRAINING,
+               DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
+               DEMOD_GOT_FALLING_EDGE_OF_SOF,
+               DEMOD_AWAITING_START_BIT,
+               DEMOD_RECEIVING_DATA
+       }       state;
+       int     bitCount;
+       int     posCount;
+       int     thisBit;
+/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
+       int     metric;
+       int     metricN;
+*/
+       uint16_t    shiftReg;
+       uint8_t   *output;
+       int     len;
+       int     sumI;
+       int     sumQ;
+} Demod;
+
+/*
+ * Handles reception of a bit from the tag
+ *
+ * This function is called 2 times per bit (every 4 subcarrier cycles).
+ * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 4,72us
+ *
+ * LED handling:
+ * LED C -> ON once we have received the SOF and are expecting the rest.
+ * LED C -> OFF once we have received EOF or are unsynced
+ *
+ * Returns: true if we received a EOF
+ *          false if we are still waiting for some more
+ *
+ */
+static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
+{
+       int v;
+
+// The soft decision on the bit uses an estimate of just the
+// quadrant of the reference angle, not the exact angle.
+#define MAKE_SOFT_DECISION() { \
+               if(Demod.sumI > 0) { \
+                       v = ci; \
+               } else { \
+                       v = -ci; \
+               } \
+               if(Demod.sumQ > 0) { \
+                       v += cq; \
+               } else { \
+                       v -= cq; \
+               } \
+       }
+
+#define SUBCARRIER_DETECT_THRESHOLD    8
+
+// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq)
+/* #define CHECK_FOR_SUBCARRIER() { \
+               v = ci; \
+               if(v < 0) v = -v; \
+               if(cq > 0) { \
+                       v += cq; \
+               } else { \
+                       v -= cq; \
+               } \
+       }               
+ */
+// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+#define CHECK_FOR_SUBCARRIER() { \
+               if(ci < 0) { \
+                       if(cq < 0) { /* ci < 0, cq < 0 */ \
+                               if (cq < ci) { \
+                                       v = -cq - (ci >> 1); \
+                               } else { \
+                                       v = -ci - (cq >> 1); \
+                               } \
+                       } else {        /* ci < 0, cq >= 0 */ \
+                               if (cq < -ci) { \
+                                       v = -ci + (cq >> 1); \
+                               } else { \
+                                       v = cq - (ci >> 1); \
+                               } \
+                       } \
+               } else { \
+                       if(cq < 0) { /* ci >= 0, cq < 0 */ \
+                               if (-cq < ci) { \
+                                       v = ci - (cq >> 1); \
+                               } else { \
+                                       v = -cq + (ci >> 1); \
+                               } \
+                       } else {        /* ci >= 0, cq >= 0 */ \
+                               if (cq < ci) { \
+                                       v = ci + (cq >> 1); \
+                               } else { \
+                                       v = cq + (ci >> 1); \
+                               } \
+                       } \
+               } \
+       }
+       
+       switch(Demod.state) {
+               case DEMOD_UNSYNCD:
+                       CHECK_FOR_SUBCARRIER();
+                       if(v > SUBCARRIER_DETECT_THRESHOLD) {   // subcarrier detected
+                               Demod.state = DEMOD_PHASE_REF_TRAINING;
+                               Demod.sumI = ci;
+                               Demod.sumQ = cq;
+                               Demod.posCount = 1;
+                               }
+                       break;
+
+               case DEMOD_PHASE_REF_TRAINING:
+                       if(Demod.posCount < 8) {
+                               CHECK_FOR_SUBCARRIER();
+                               if (v > SUBCARRIER_DETECT_THRESHOLD) {
+                                       // set the reference phase (will code a logic '1') by averaging over 32 1/fs.
+                                       // note: synchronization time > 80 1/fs
+                                       Demod.sumI += ci;
+                                       Demod.sumQ += cq;
+                                       Demod.posCount++;
+                               } else {                // subcarrier lost
+                                       Demod.state = DEMOD_UNSYNCD;
+                               }
+                       } else {
+                               Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
+                       }
+                       break;
+
+               case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
+                       MAKE_SOFT_DECISION();
+                       if(v < 0) {     // logic '0' detected
+                               Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
+                               Demod.posCount = 0;     // start of SOF sequence
+                       } else {
+                               if(Demod.posCount > 200/4) {    // maximum length of TR1 = 200 1/fs
+                                       Demod.state = DEMOD_UNSYNCD;
+                               }
+                       }
+                       Demod.posCount++;
+                       break;
+
+               case DEMOD_GOT_FALLING_EDGE_OF_SOF:
+                       Demod.posCount++;
+                       MAKE_SOFT_DECISION();
+                       if(v > 0) {
+                               if(Demod.posCount < 9*2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
+                                       Demod.state = DEMOD_UNSYNCD;
+                               } else {
+                                       LED_C_ON(); // Got SOF
+                                       Demod.state = DEMOD_AWAITING_START_BIT;
+                                       Demod.posCount = 0;
+                                       Demod.len = 0;
+/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
+                                       Demod.metricN = 0;
+                                       Demod.metric = 0;
+*/
+                               }
+                       } else {
+                               if(Demod.posCount > 12*2) { // low phase of SOF too long (> 12 etu)
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       LED_C_OFF();
+                               }
+                       }
+                       break;
+
+               case DEMOD_AWAITING_START_BIT:
+                       Demod.posCount++;
+                       MAKE_SOFT_DECISION();
+                       if(v > 0) {
+                               if(Demod.posCount > 3*2) {              // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       LED_C_OFF();
+                               }
+                       } else {                                                        // start bit detected
+                               Demod.bitCount = 0;
+                               Demod.posCount = 1;                             // this was the first half
+                               Demod.thisBit = v;
+                               Demod.shiftReg = 0;
+                               Demod.state = DEMOD_RECEIVING_DATA;
+                       }
+                       break;
+
+               case DEMOD_RECEIVING_DATA:
+                       MAKE_SOFT_DECISION();
+                       if(Demod.posCount == 0) {                       // first half of bit
+                               Demod.thisBit = v;
+                               Demod.posCount = 1;
+                       } else {                                                        // second half of bit
+                               Demod.thisBit += v;
+
+/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
+                               if(Demod.thisBit > 0) {
+                                       Demod.metric += Demod.thisBit;
+                               } else {
+                                       Demod.metric -= Demod.thisBit;
+                               }
+                               (Demod.metricN)++;
+*/                             
+
+                               Demod.shiftReg >>= 1;
+                               if(Demod.thisBit > 0) { // logic '1'
+                                       Demod.shiftReg |= 0x200;
+                               }
+
+                               Demod.bitCount++;
+                               if(Demod.bitCount == 10) {
+                                       uint16_t s = Demod.shiftReg;
+                                       if((s & 0x200) && !(s & 0x001)) { // stop bit == '1', start bit == '0'
+                                               uint8_t b = (s >> 1);
+                                               Demod.output[Demod.len] = b;
+                                               Demod.len++;
+                                               Demod.state = DEMOD_AWAITING_START_BIT;
+                                       } else {
+                                               Demod.state = DEMOD_UNSYNCD;
+                                               LED_C_OFF();
+                                               if(s == 0x000) {
+                                                       // This is EOF (start, stop and all data bits == '0'
+                                                       return TRUE;
+                                               }
+                                       }
+                               }
+                               Demod.posCount = 0;
+                       }
+                       break;
+
+               default:
+                       Demod.state = DEMOD_UNSYNCD;
+                       LED_C_OFF();
+                       break;
+       }
+
+       return FALSE;
+}
+
+
+static void DemodReset()
+{
+       // Clear out the state of the "UART" that receives from the tag.
+       Demod.len = 0;
+       Demod.state = DEMOD_UNSYNCD;
+       Demod.posCount = 0;
+       memset(Demod.output, 0x00, MAX_FRAME_SIZE);
+}
+
+
+static void DemodInit(uint8_t *data)
+{
+       Demod.output = data;
+       DemodReset();
+}
+
+
+/*
+ *  Demodulate the samples we received from the tag, also log to tracebuffer
+ *  quiet: set to 'TRUE' to disable debug output
+ */
+static void GetSamplesFor14443bDemod(int n, bool quiet)
+{
+       int max = 0;
+       bool gotFrame = FALSE;
+       int lastRxCounter, ci, cq, samples = 0;
+
+       // Allocate memory from BigBuf for some buffers
+       // free all previous allocations first
+       BigBuf_free();
+       
+       // The response (tag -> reader) that we're receiving.
+       uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
+       
+       // The DMA buffer, used to stream samples from the FPGA
+       int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
+
+       // Set up the demodulator for tag -> reader responses.
+       DemodInit(receivedResponse);
+
+       // Setup and start DMA.
+       FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
+
+       int8_t *upTo = dmaBuf;
+       lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
+
+       // Signal field is ON with the appropriate LED:
+       LED_D_ON();
+       // And put the FPGA in the appropriate mode
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
+
+       for(;;) {
+               int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
+               if(behindBy > max) max = behindBy;
+
+               while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1)) > 2) {
+                       ci = upTo[0];
+                       cq = upTo[1];
+                       upTo += 2;
+                       if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
+                               upTo = dmaBuf;
+                               AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
+                               AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
+                       }
+                       lastRxCounter -= 2;
+                       if(lastRxCounter <= 0) {
+                               lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
+                       }
+
+                       samples += 2;
+
+                       if(Handle14443bSamplesDemod(ci, cq)) {
+                               gotFrame = TRUE;
+                               break;
+                       }
+               }
+
+               if(samples > n || gotFrame) {
+                       break;
+               }
+       }
+
+       AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+
+       if (!quiet) Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d", max, samples, gotFrame, Demod.len, Demod.sumI, Demod.sumQ);
+       //Tracing
+       if (tracing && Demod.len > 0) {
+               uint8_t parity[MAX_PARITY_SIZE];
+               LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE);
+       }
+}
+
+
+//-----------------------------------------------------------------------------
+// Transmit the command (to the tag) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitFor14443b(void)
+{
+       int c;
+
+       FpgaSetupSsc();
+
+       while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+               AT91C_BASE_SSC->SSC_THR = 0xff;
+       }
+
+       // Signal field is ON with the appropriate Red LED
+       LED_D_ON();
+       // Signal we are transmitting with the Green LED
+       LED_B_ON();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
+
+       for(c = 0; c < 10;) {
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                       AT91C_BASE_SSC->SSC_THR = 0xff;
+                       c++;
+               }
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+                       (void)r;
+               }
+               WDT_HIT();
+       }
+
+       c = 0;
+       for(;;) {
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                       AT91C_BASE_SSC->SSC_THR = ToSend[c];
+                       c++;
+                       if(c >= ToSendMax) {
+                               break;
+                       }
+               }
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+                       (void)r;
+               }
+               WDT_HIT();
+       }
+       LED_B_OFF(); // Finished sending
+}
+
+
+//-----------------------------------------------------------------------------
+// Code a layer 2 command (string of octets, including CRC) into ToSend[],
+// so that it is ready to transmit to the tag using TransmitFor14443b().
+//-----------------------------------------------------------------------------
+static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
+{
+       int i, j;
+       uint8_t b;
+
+       ToSendReset();
+
+       // Establish initial reference level
+       for(i = 0; i < 40; i++) {
+               ToSendStuffBit(1);
+       }
+       // Send SOF
+       for(i = 0; i < 10; i++) {
+               ToSendStuffBit(0);
+       }
+
+       for(i = 0; i < len; i++) {
+               // Stop bits/EGT
+               ToSendStuffBit(1);
+               ToSendStuffBit(1);
+               // Start bit
+               ToSendStuffBit(0);
+               // Data bits
+               b = cmd[i];
+               for(j = 0; j < 8; j++) {
+                       if(b & 1) {
+                               ToSendStuffBit(1);
+                       } else {
+                               ToSendStuffBit(0);
+                       }
+                       b >>= 1;
+               }
+       }
+       // Send EOF
+       ToSendStuffBit(1);
+       for(i = 0; i < 10; i++) {
+               ToSendStuffBit(0);
+       }
+       for(i = 0; i < 8; i++) {
+               ToSendStuffBit(1);
+       }
+
+       // And then a little more, to make sure that the last character makes
+       // it out before we switch to rx mode.
+       for(i = 0; i < 24; i++) {
+               ToSendStuffBit(1);
+       }
+
+       // Convert from last character reference to length
+       ToSendMax++;
+}
+
+
+/**
+  Convenience function to encode, transmit and trace iso 14443b comms
+  **/
+static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len)
+{
+       CodeIso14443bAsReader(cmd, len);
+       TransmitFor14443b();
+       if (tracing) {
+               uint8_t parity[MAX_PARITY_SIZE];
+               LogTrace(cmd,len, 0, 0, parity, TRUE);
+       }
+}
+
+
+//-----------------------------------------------------------------------------
+// Read a SRI512 ISO 14443B tag.
+//
+// SRI512 tags are just simple memory tags, here we're looking at making a dump
+// of the contents of the memory. No anticollision algorithm is done, we assume
+// we have a single tag in the field.
+//
+// I tried to be systematic and check every answer of the tag, every CRC, etc...
+//-----------------------------------------------------------------------------
+void ReadSTMemoryIso14443b(uint32_t dwLast)
+{
+       clear_trace();
+       set_tracing(TRUE);
+
+       uint8_t i = 0x00;
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+       // Make sure that we start from off, since the tags are stateful;
+       // confusing things will happen if we don't reset them between reads.
+       LED_D_OFF();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       SpinDelay(200);
+
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+       FpgaSetupSsc();
+
+       // Now give it time to spin up.
+       // Signal field is on with the appropriate LED
+       LED_D_ON();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
+       SpinDelay(200);
+
+       // First command: wake up the tag using the INITIATE command
+       uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b};
+       CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
+       GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+
+       if (Demod.len == 0) {
+               DbpString("No response from tag");
+               return;
+       } else {
+               Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x",
+                               Demod.output[0], Demod.output[1], Demod.output[2]);
+       }
+
+       // There is a response, SELECT the uid
+       DbpString("Now SELECT tag:");
+       cmd1[0] = 0x0E; // 0x0E is SELECT
+       cmd1[1] = Demod.output[0];
+       ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
+       CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
+       GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+       if (Demod.len != 3) {
+               Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
+               return;
+       }
+       // Check the CRC of the answer:
+       ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
+       if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
+               DbpString("CRC Error reading select response.");
+               return;
+       }
+       // Check response from the tag: should be the same UID as the command we just sent:
+       if (cmd1[1] != Demod.output[0]) {
+               Dbprintf("Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]);
+               return;
+       }
+
+       // Tag is now selected,
+       // First get the tag's UID:
+       cmd1[0] = 0x0B;
+       ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
+       CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one
+       GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+       if (Demod.len != 10) {
+               Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
+               return;
+       }
+       // The check the CRC of the answer (use cmd1 as temporary variable):
+       ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);
+       if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {
+               Dbprintf("CRC Error reading block! Expected: %04x got: %04x",
+                               (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);
+               // Do not return;, let's go on... (we should retry, maybe ?)
+       }
+       Dbprintf("Tag UID (64 bits): %08x %08x",
+                       (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],
+                       (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
+
+       // Now loop to read all 16 blocks, address from 0 to last block
+       Dbprintf("Tag memory dump, block 0 to %d", dwLast);
+       cmd1[0] = 0x08;
+       i = 0x00;
+       dwLast++;
+       for (;;) {
+               if (i == dwLast) {
+                       DbpString("System area block (0xff):");
+                       i = 0xff;
+               }
+               cmd1[1] = i;
+               ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
+               CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1));
+               GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+               if (Demod.len != 6) { // Check if we got an answer from the tag
+                       DbpString("Expected 6 bytes from tag, got less...");
+                       return;
+               }
+               // The check the CRC of the answer (use cmd1 as temporary variable):
+               ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);
+               if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {
+                       Dbprintf("CRC Error reading block! Expected: %04x got: %04x",
+                                       (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);
+                       // Do not return;, let's go on... (we should retry, maybe ?)
+               }
+               // Now print out the memory location:
+               Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
+                               (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
+                               (Demod.output[4]<<8)+Demod.output[5]);
+               if (i == 0xff) {
+                       break;
+               }
+               i++;
+       }
+}
+
+
+//=============================================================================
+// Finally, the `sniffer' combines elements from both the reader and
+// simulated tag, to show both sides of the conversation.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Record the sequence of commands sent by the reader to the tag, with
+// triggering so that we start recording at the point that the tag is moved
+// near the reader.
+//-----------------------------------------------------------------------------
+/*
+ * Memory usage for this function, (within BigBuf)
+ * Last Received command (reader->tag) - MAX_FRAME_SIZE
+ * Last Received command (tag->reader) - MAX_FRAME_SIZE
+ * DMA Buffer - ISO14443B_DMA_BUFFER_SIZE
+ * Demodulated samples received - all the rest
+ */
+void RAMFUNC SnoopIso14443b(void)
+{
+       // 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
+       // response from the tag.
+       int triggered = TRUE;                   // TODO: set and evaluate trigger condition
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+       BigBuf_free();
+
+       clear_trace();
+       set_tracing(TRUE);
+
+       // The DMA buffer, used to stream samples from the FPGA
+       int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
+       int lastRxCounter;
+       int8_t *upTo;
+       int ci, cq;
+       int maxBehindBy = 0;
+
+       // Count of samples received so far, so that we can include timing
+       // information in the trace buffer.
+       int samples = 0;
+
+       DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
+       UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
+
+       // Print some debug information about the buffer sizes
+       Dbprintf("Snooping buffers initialized:");
+       Dbprintf("  Trace: %i bytes", BigBuf_max_traceLen());
+       Dbprintf("  Reader -> tag: %i bytes", MAX_FRAME_SIZE);
+       Dbprintf("  tag -> Reader: %i bytes", MAX_FRAME_SIZE);
+       Dbprintf("  DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE);
+
+       // Signal field is off, no reader signal, no tag signal
+       LEDsoff();
+
+       // And put the FPGA in the appropriate mode
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+       // Setup for the DMA.
+       FpgaSetupSsc();
+       upTo = dmaBuf;
+       lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
+       FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
+       uint8_t parity[MAX_PARITY_SIZE];
+
+       bool TagIsActive = FALSE;
+       bool ReaderIsActive = FALSE;
+       
+       // And now we loop, receiving samples.
+       for(;;) {
+               int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
+                                                               (ISO14443B_DMA_BUFFER_SIZE-1);
+               if(behindBy > maxBehindBy) {
+                       maxBehindBy = behindBy;
+               }
+
+               if(behindBy < 2) continue;
+
+               ci = upTo[0];
+               cq = upTo[1];
+               upTo += 2;
+               lastRxCounter -= 2;
+               if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
+                       upTo = dmaBuf;
+                       lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
+                       AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
+                       AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
+                       WDT_HIT();
+                       if(behindBy > (9*ISO14443B_DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
+                               Dbprintf("blew circular buffer! behindBy=%d", behindBy);
+                               break;
+                       }
+                       if(!tracing) {
+                               DbpString("Reached trace limit");
+                               break;
+                       }
+                       if(BUTTON_PRESS()) {
+                               DbpString("cancelled");
+                               break;
+                       }
+               }
+
+               samples += 2;
+
+               if (!TagIsActive) {                                                     // no need to try decoding reader data if the tag is sending
+                       if(Handle14443bUartBit(ci & 0x01)) {
+                               if(triggered && tracing) {
+                                       LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
+                               }
+                               /* And ready to receive another command. */
+                               UartReset();
+                               /* And also reset the demod code, which might have been */
+                               /* false-triggered by the commands from the reader. */
+                               DemodReset();
+                       }
+                       if(Handle14443bUartBit(cq & 0x01)) {
+                               if(triggered && tracing) {
+                                       LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE);
+                               }
+                               /* And ready to receive another command. */
+                               UartReset();
+                               /* And also reset the demod code, which might have been */
+                               /* false-triggered by the commands from the reader. */
+                               DemodReset();
+                       }
+                       ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
+               }
+
+               if(!ReaderIsActive) {                                           // no need to try decoding tag data if the reader is sending - and we cannot afford the time
+                       if(Handle14443bSamplesDemod(ci | 0x01, cq | 0x01)) {
+
+                               //Use samples as a time measurement
+                               if(tracing)
+                               {
+                                       uint8_t parity[MAX_PARITY_SIZE];
+                                       LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE);
+                               }
+                               triggered = TRUE;
+
+                               // And ready to receive another response.
+                               DemodReset();
+                       }
+                       TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF);
+               }
+
+       }
+
+       FpgaDisableSscDma();
+       LEDsoff();
+       AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+       DbpString("Snoop statistics:");
+       Dbprintf("  Max behind by: %i", maxBehindBy);
+       Dbprintf("  Uart State: %x", Uart.state);
+       Dbprintf("  Uart ByteCnt: %i", Uart.byteCnt);
+       Dbprintf("  Uart ByteCntMax: %i", Uart.byteCntMax);
+       Dbprintf("  Trace length: %i", BigBuf_get_traceLen());
+}
+
+
+/*
+ * Send raw command to tag ISO14443B
+ * @Input
+ * datalen     len of buffer data
+ * recv        bool when true wait for data from tag and send to client
+ * powerfield  bool leave the field on when true
+ * data        buffer with byte to send
+ *
+ * @Output
+ * none
+ *
+ */
+void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[])
+{
+       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+       FpgaSetupSsc();
+
+       set_tracing(TRUE);
+       
+       CodeAndTransmit14443bAsReader(data, datalen);
+
+       if(recv) {
+               GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+               uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE);
+               cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen);
+       }
+       
+       if(!powerfield) {
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+               LED_D_OFF();
+       }
+}
+
index c3fa8a0e630f2f743aaedd247b2d711c89610385..7e53d4a566173d97301f9e56ee1e5ad01a1ca15e 100644 (file)
@@ -1024,10 +1024,10 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
  * To compensate antenna falling times shorten the write times
  * and enlarge the gap ones.
  */
-#define START_GAP 50*8 // 10 - 50fc 250
-#define WRITE_GAP 20*8 //    - 30fc 160
-#define WRITE_0   24*8 // 16 - 63fc 54fc 144
-#define WRITE_1   54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550 //400
+#define START_GAP 31*8 // was 250 // SPEC:  1*8 to 50*8 - typ 15*8 (or 15fc)
+#define WRITE_GAP 20*8 // was 160 // SPEC:  1*8 to 20*8 - typ 10*8 (or 10fc)
+#define WRITE_0   18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (or 24fc)
+#define WRITE_1   50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (or 56fc)  432 for T55x7; 448 for E5550
 
 #define T55xx_SAMPLES_SIZE      12000 // 32 x 32 x 10  (32 bit times numofblock (7), times clock skip..)
 
index 8355cd1946172da7c7cdf272938179bc95fef66a..939c90028796ef823e0e0c3d5acfbd841cf4f48f 100644 (file)
@@ -16,7 +16,6 @@
 #include "mifarecmd.h"\r
 #include "apps.h"\r
 #include "util.h"\r
-\r
 #include "crc.h"\r
 \r
 // the block number for the ISO14443-4 PCB\r
@@ -24,7 +23,6 @@ uint8_t pcb_blocknum = 0;
 // Deselect card by sending a s-block. the crc is precalced for speed\r
 static  uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};\r
 \r
-\r
 //-----------------------------------------------------------------------------\r
 // Select, Authenticate, Read a MIFARE tag. \r
 // read block\r
@@ -248,11 +246,14 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        LEDsoff();\r
 }\r
 \r
+// arg0 = blockNo (start)\r
+// arg1 = Pages (number of blocks)\r
+// arg2 = useKey\r
+// datain = KEY bytes\r
 void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
 {\r
        // free eventually allocated BigBuf memory\r
        BigBuf_free();\r
-       // clear trace\r
        clear_trace();\r
 \r
        // params\r
@@ -303,7 +304,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
        }\r
 \r
        for (int i = 0; i < blocks; i++){\r
-               if ((i*4) + 4 > CARD_MEMORY_SIZE) {\r
+               if ((i*4) + 4 >= CARD_MEMORY_SIZE) {\r
                        Dbprintf("Data exceeds buffer!!");\r
                        break;\r
                }\r
@@ -335,9 +336,11 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);\r
 \r
        countblocks *= 4;\r
+\r
        cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
+       BigBuf_free();\r
 }\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -412,7 +415,8 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        LEDsoff();\r
 }\r
 \r
-void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)\r
+/* // Command not needed but left for future testing \r
+void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)\r
 {\r
        uint8_t blockNo = arg0;\r
        byte_t blockdata[16] = {0x00};\r
@@ -432,7 +436,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)
                return;\r
        };\r
 \r
-       if(mifare_ultra_writeblock(blockNo, blockdata)) {\r
+       if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {\r
                if (MF_DBGLEVEL >= 1)   Dbprintf("Write block error");\r
                OnError(0);\r
                return; };\r
@@ -449,10 +453,19 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
 }\r
-\r
-void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)\r
+*/\r
+\r
+// Arg0   : Block to write to.\r
+// Arg1   : 0 = use no authentication.\r
+//          1 = use 0x1A authentication.\r
+//          2 = use 0x1B authentication.\r
+// datain : 4 first bytes is data to be written.\r
+//        : 4/16 next bytes is authentication key.\r
+void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
 {\r
        uint8_t blockNo = arg0;\r
+       bool useKey = (arg1 == 1); //UL_C\r
+       bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
        byte_t blockdata[4] = {0x00};\r
 \r
        memcpy(blockdata, datain,4);\r
@@ -468,7 +481,29 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
                return;\r
        };\r
 \r
-       if(mifare_ultra_special_writeblock(blockNo, blockdata)) {\r
+       // UL-C authentication\r
+       if ( useKey ) {\r
+               uint8_t key[16] = {0x00};\r
+               memcpy(key, datain+4, sizeof(key) );\r
+\r
+               if ( !mifare_ultra_auth(key) ) {\r
+                       OnError(1);\r
+                       return;\r
+               }\r
+       }\r
+       \r
+       // UL-EV1 / NTAG authentication\r
+       if (usePwd) {\r
+               uint8_t pwd[4] = {0x00};\r
+               memcpy(pwd, datain+4, 4);\r
+               uint8_t pack[4] = {0,0,0,0};\r
+               if (!mifare_ul_ev1_auth(pwd, pack)) {\r
+                       OnError(1);\r
+                       return;\r
+               }\r
+       }\r
+\r
+       if(mifare_ultra_writeblock(blockNo, blockdata)) {\r
                if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
                OnError(0);\r
                return;\r
@@ -508,7 +543,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
        blockdata[1] = pwd[6];\r
        blockdata[2] = pwd[5];\r
        blockdata[3] = pwd[4];\r
-       if(mifare_ultra_special_writeblock( 44, blockdata)) {\r
+       if(mifare_ultra_writeblock( 44, blockdata)) {\r
                if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
                OnError(44);\r
                return;\r
@@ -518,7 +553,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
        blockdata[1] = pwd[2];\r
        blockdata[2] = pwd[1];\r
        blockdata[3] = pwd[0];\r
-       if(mifare_ultra_special_writeblock( 45, blockdata)) {\r
+       if(mifare_ultra_writeblock( 45, blockdata)) {\r
                if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
                OnError(45);\r
                return;\r
@@ -528,7 +563,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
        blockdata[1] = pwd[14];\r
        blockdata[2] = pwd[13];\r
        blockdata[3] = pwd[12];\r
-       if(mifare_ultra_special_writeblock( 46, blockdata)) {\r
+       if(mifare_ultra_writeblock( 46, blockdata)) {\r
                if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
                OnError(46);\r
                return;\r
@@ -538,7 +573,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
        blockdata[1] = pwd[10];\r
        blockdata[2] = pwd[9];\r
        blockdata[3] = pwd[8];\r
-       if(mifare_ultra_special_writeblock( 47, blockdata)) {\r
+       if(mifare_ultra_writeblock( 47, blockdata)) {\r
                if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
                OnError(47);\r
                return;\r
@@ -682,7 +717,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
                LED_B_OFF();\r
        \r
        }\r
-//  -------------------------------------------------------------------------------------------------  \r
+       //  -------------------------------------------------------------------------------------------------   \r
        \r
        LED_C_ON();\r
 \r
@@ -711,7 +746,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 \r
                        // nested authentication\r
                        auth2_time = auth1_time + delta_time;\r
-                       len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);\r
+                       len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);\r
                        if (len != 4) {\r
                                if (MF_DBGLEVEL >= 1)   Dbprintf("Nested: Auth2 error len=%d", len);\r
                                continue;\r
@@ -1231,14 +1266,12 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
        isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
        \r
        if( isOK) {\r
-           if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
-                       Dbprintf("Authentication part2: Failed");  \r
-               //OnError(4);\r
+               if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");  \r
+               OnError(4);\r
                return;\r
        }\r
 \r
-       if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
-               DbpString("AUTH 2 FINISHED");\r
+       if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
 \r
        cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
index 2f84797b92e015384d8b2755410bd4c553431efd..8ef364c259f0d16216834a87dac9bef073be1e92 100644 (file)
@@ -65,74 +65,25 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
        return bt;\r
 }\r
 \r
-// send commands\r
-int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
+// send X byte basic commands\r
+int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
 {\r
-       return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);\r
-}\r
-\r
-int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
-{\r
-       uint8_t dcmd[8];\r
-    dcmd[0] = cmd;\r
-    dcmd[1] = data[0];\r
-       dcmd[2] = data[1];\r
-       dcmd[3] = data[2];\r
-       dcmd[4] = data[3];\r
-       dcmd[5] = data[4];\r
-       AppendCrc14443a(dcmd, 6);\r
-       ReaderTransmit(dcmd, sizeof(dcmd), NULL);\r
-       int len = ReaderReceive(answer, answer_parity);\r
-       if(!len) {\r
-                if (MF_DBGLEVEL >= 1)   Dbprintf("Authentication failed. Card timeout.");\r
-                return 2;\r
-    }\r
-       return len;\r
-}\r
-\r
-int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)\r
-{\r
-    uint8_t dcmd[19];\r
-       int len; \r
-    dcmd[0] = cmd;\r
-    memcpy(dcmd+1,data,16);\r
-       AppendCrc14443a(dcmd, 17);\r
-       \r
-       ReaderTransmit(dcmd, sizeof(dcmd), timing);\r
-       len = ReaderReceive(answer, answer_parity);\r
-       if(!len) {\r
-        if (MF_DBGLEVEL >= MF_DBG_ERROR)   Dbprintf("Authentication failed. Card timeout.");\r
-        len = ReaderReceive(answer,answer_parity);\r
-    }\r
-    if(len==1) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)   Dbprintf("NAK - Authentication failed.");\r
-               return 1;\r
-        }\r
-       return len;\r
-}\r
-\r
-int mifare_sendcmd_short_mfuev1auth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)\r
-{\r
-    uint8_t dcmd[7];\r
-       int len; \r
-    dcmd[0] = cmd;\r
-    memcpy(dcmd+1,data,4);\r
-       AppendCrc14443a(dcmd, 5);\r
-       \r
+       uint8_t dcmd[data_size+3];\r
+       dcmd[0] = cmd;\r
+       memcpy(dcmd+1,data,data_size);\r
+       AppendCrc14443a(dcmd, data_size+1);\r
        ReaderTransmit(dcmd, sizeof(dcmd), timing);\r
-       len = ReaderReceive(answer, answer_parity);\r
+       int len = ReaderReceive(answer, answer_parity);\r
        if(!len) {\r
-        if (MF_DBGLEVEL >= MF_DBG_ERROR)   Dbprintf("Authentication failed. Card timeout.");\r
-        len = ReaderReceive(answer,answer_parity);\r
-    }\r
-    if(len==1) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)   Dbprintf("NAK - Authentication failed.");\r
-               return 1;\r
-        }\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR)   Dbprintf("%02X Cmd failed. Card timeout.", cmd);\r
+                       len = ReaderReceive(answer,answer_parity);\r
+               //return 0;\r
+       }\r
        return len;\r
 }\r
 \r
-int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)\r
+// send 2 byte commands\r
+int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)\r
 {\r
        uint8_t dcmd[4], ecmd[4];\r
        uint16_t pos, res;\r
@@ -318,8 +269,10 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
        uint8_t key[4] = {0x00};\r
        memcpy(key, keybytes, 4);\r
 \r
-       Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);\r
-       len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);\r
+       if (MF_DBGLEVEL >= MF_DBG_EXTENDED)\r
+               Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);\r
+       len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL);\r
+       //len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);\r
        if (len != 4) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);\r
                return 0;\r
@@ -380,8 +333,8 @@ int mifare_ultra_auth(uint8_t *keybytes){
 \r
        // encrypt    out, in, length, key, iv\r
        tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);\r
-\r
-       len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);\r
+       //len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);\r
+       len = mifare_sendcmd(0xAF, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);\r
        if (len != 11) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);\r
                return 0;\r
@@ -425,6 +378,7 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)
        uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
+\r
        len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
        if (len == 1) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
@@ -493,7 +447,8 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
        return 0;\r
 }\r
 \r
-int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) \r
+/* // command not needed, but left for future testing\r
+int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) \r
 {\r
        uint16_t len;\r
        uint8_t par[3] = {0};  // enough for 18 parity bits\r
@@ -501,7 +456,6 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData)
        uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
 \r
-       // command MIFARE_CLASSIC_WRITEBLOCK\r
        len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
 \r
        if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
@@ -524,20 +478,21 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData)
        }\r
        return 0;\r
 }\r
+*/\r
 \r
-int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData)\r
+int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData)\r
 {\r
        uint16_t len;\r
-       uint8_t d_block[8] = {0x00};\r
+       uint8_t d_block[5] = {0x00};\r
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
 \r
        // command MIFARE_CLASSIC_WRITEBLOCK\r
        d_block[0]= blockNo;\r
        memcpy(d_block+1,blockData,4);\r
-       AppendCrc14443a(d_block, 6);\r
+       //AppendCrc14443a(d_block, 6);\r
 \r
-       len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);\r
+       len = mifare_sendcmd(0xA2, d_block, sizeof(d_block), receivedAnswer, receivedAnswerPar, NULL);\r
 \r
        if (receivedAnswer[0] != 0x0A) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
index d4fcd818932e4cf66299edd53044e00f9432fb2f..85a34ef62104fa2445503eac3517436d43fa8438 100644 (file)
@@ -53,23 +53,22 @@ extern int MF_DBGLEVEL;
 #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();\r
 \r
 //functions\r
+int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
 int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
-int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
-\r
-int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);\r
-int mifare_sendcmd_short_mfuev1auth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);\r
-int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
 \r
+// mifare classic\r
 int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);\r
 int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);\r
 int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
+int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); \r
+int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
+\r
+// Ultralight/NTAG...\r
 int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack);\r
 int mifare_ultra_auth(uint8_t *key);\r
 int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);\r
-int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
+//int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);\r
 int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);\r
-int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData);\r
-int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); \r
 int mifare_ultra_halt();\r
 \r
 // desfire\r
index 444b93d09f688db68b71d152745c3a92f84c6b43..2356262114da1123395e534fab0e30da579743b9 100644 (file)
@@ -61,7 +61,6 @@
 **/
 
 #include "optimized_cipher.h"
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
index f9645194829c888a825da7dc545fee5f0af9710a..c454533d7822ca63febae2f6152a28f4480cb0bf 100644 (file)
@@ -102,6 +102,7 @@ CMDSRCS =   nonce2key/crapto1.c\
                        pm3_bitlib.c\
                        aes.c\
                        protocols.c\
+                       sha1.c\
 
 ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
 ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED 
index b9069bc19cb82b150b05de62345a188a56e5f6aa..bec1b5aa3f4d4394f011394fa61edca5b9a06767 100644 (file)
@@ -23,6 +23,7 @@
 #include "lfdemod.h"
 #include "usb_cmd.h"
 #include "crc.h"
+#include "crc16.h"
 
 uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 uint8_t g_debugMode;
@@ -55,6 +56,15 @@ int CmdSetDebugMode(const char *Cmd)
        return 1;
 }
 
+int usage_data_printdemodbuf(){
+               PrintAndLog("Usage: data printdemodbuffer x o <offset>");
+               PrintAndLog("Options:        ");
+               PrintAndLog("       h          This help");
+               PrintAndLog("       x          output in hex (omit for binary output)");
+               PrintAndLog("       o <offset> enter offset in # of bits");
+               return 0;       
+}
+
 //by marshmellow
 void printDemodBuff(void)
 {
@@ -73,23 +83,50 @@ void printDemodBuff(void)
 
 int CmdPrintDemodBuff(const char *Cmd)
 {
-       char hex;
-       char printBuff[512]={0x00};
-       uint8_t numBits = DemodBufferLen & 0xFFFC;
-       sscanf(Cmd, "%c", &hex);
-       if (hex == 'h'){
-               PrintAndLog("Usage: data printdemodbuffer [x]");
-               PrintAndLog("Options:        ");
-               PrintAndLog("       h       This help");
-               PrintAndLog("       x       output in hex (omit for binary output)");
-               return 0;
+       char hex[512]={0x00};
+       bool hexMode = false;
+       bool errors = false;
+       uint8_t offset = 0;
+       char cmdp = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_data_printdemodbuf();
+               case 'x':
+               case 'X':
+                       hexMode = true;
+                       cmdp++;
+                       break;
+               case 'o':
+               case 'O':
+                       offset = param_get8(Cmd, cmdp+1);
+                       if (!offset) errors = true;
+                       cmdp += 2;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) break;
        }
-       if (hex == 'x'){
-               numBits = binarraytohex(printBuff, (char *)DemodBuffer, numBits);
+       //Validations
+       if(errors) return usage_data_printdemodbuf();
+
+       int numBits = (DemodBufferLen-offset) & 0x7FC; //make sure we don't exceed our string
+
+       if (hexMode){
+               char *buf = (char *) (DemodBuffer + offset);
+               numBits = binarraytohex(hex, buf, numBits);
                if (numBits==0) return 0;
-               PrintAndLog("DemodBuffer: %s",printBuff);
+               PrintAndLog("DemodBuffer: %s",hex);             
        } else {
-               printDemodBuff();
+               //setDemodBuf(DemodBuffer, DemodBufferLen-offset, offset);
+               char *bin = sprint_bin_break(DemodBuffer+offset,numBits,16);
+               PrintAndLog("DemodBuffer:\n%s",bin);
        }
        return 1;
 }
@@ -307,8 +344,8 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
        setDemodBuf(BitStream,BitLen,0);
        if (verbose || g_debugMode){
                if (errCnt>0) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt);
-               if (askType) PrintAndLog("ASK/Manchester decoded bitstream:");
-               else PrintAndLog("ASK/Raw decoded bitstream:");
+               if (askType) PrintAndLog("ASK/Manchester - Clock: %d - Decoded bitstream:",clk);
+               else PrintAndLog("ASK/Raw - Clock: %d - Decoded bitstream:",clk);
                // Now output the bitstream to the scrollback by line of 16 bits
                printDemodBuff();
                
@@ -355,7 +392,7 @@ int Cmdmandecoderaw(const char *Cmd)
        int errCnt=0;
        size_t size=0;
        int invert=0;
-       size_t maxErr = 20;
+       int maxErr = 20;
        char cmdp = param_getchar(Cmd, 0);
        if (strlen(Cmd) > 5 || cmdp == 'h' || cmdp == 'H') {
                PrintAndLog("Usage:  data manrawdecode [invert] [maxErr]");
@@ -461,22 +498,20 @@ int CmdBiphaseDecodeRaw(const char *Cmd)
 int ASKbiphaseDemod(const char *Cmd, bool verbose)
 {
        //ask raw demod GraphBuffer first
-       int offset=0, clk=0, invert=0, maxErr=0, ans=0;
-       ans = sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
-       if (ans>0)
-               ans = ASKDemod(Cmd+1, FALSE, FALSE, 0);
-       else
-               ans = ASKDemod(Cmd, FALSE, FALSE, 0);
-       if (!ans) {
-               if (g_debugMode || verbose) PrintAndLog("Error AskDemod: %d", ans);
-               return 0;
-       }
+       int offset=0, clk=0, invert=0, maxErr=0;
+       sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
+
+       uint8_t BitStream[MAX_DEMOD_BUF_LEN];     
+       size_t size = getFromGraphBuf(BitStream);         
+       //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer
+       int errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);  
+       if ( errCnt < 0 || errCnt > maxErr ) {   
+               if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);  
+                       return 0;  
+       } 
 
-       //attempt to Biphase decode DemodBuffer
-       size_t size = DemodBufferLen;
-       uint8_t BitStream[MAX_DEMOD_BUF_LEN];
-       memcpy(BitStream, DemodBuffer, DemodBufferLen); 
-       int errCnt = BiphaseRawDecode(BitStream, &size, offset, 0);
+       //attempt to Biphase decode BitStream
+       errCnt = BiphaseRawDecode(BitStream, &size, offset, invert);
        if (errCnt < 0){
                if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
                return 0;
@@ -488,7 +523,7 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose)
        //success set DemodBuffer and return
        setDemodBuf(BitStream, size, 0);
        if (g_debugMode || verbose){
-               PrintAndLog("Biphase Decoded using offset: %d - # errors:%d - data:",offset,errCnt);
+               PrintAndLog("Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt);
                printDemodBuff();
        }
        return 1;
@@ -1421,6 +1456,83 @@ int CmdFSKdemodPyramid(const char *Cmd)
        return 1;
 }
 
+// FDX-B ISO11784/85 demod  (aka animal tag)  BIPHASE, inverted, rf/32,  with preamble of 00000000001 (128bits)
+// 8 databits + 1 parity (1)
+// CIITT 16 chksum
+// NATIONAL CODE, ICAR database
+// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf
+// FLAG (animal/non-animal)
+int CmdFDXBdemodBI(const char *Cmd){
+
+       int invert = 1;
+       int clk = 32;           
+       int errCnt = 0;
+       int maxErr = 0;
+       uint8_t BitStream[MAX_DEMOD_BUF_LEN];   
+       size_t size = getFromGraphBuf(BitStream);       
+       
+       errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0);
+       if ( errCnt < 0 || errCnt > maxErr ) { 
+               if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk);
+               return 0;
+       }
+
+       errCnt = BiphaseRawDecode(BitStream, &size, maxErr, 1);
+       if (errCnt < 0 || errCnt > maxErr ) {
+               if (g_debugMode) PrintAndLog("Error BiphaseRawDecode: %d", errCnt);
+               return 0;
+       } 
+
+       int preambleIndex = FDXBdemodBI(BitStream, &size);
+       if (preambleIndex < 0){
+               if (g_debugMode) PrintAndLog("Error FDXBDemod , no startmarker found :: %d",preambleIndex);
+               return 0;
+       }
+
+       setDemodBuf(BitStream, 128, preambleIndex);
+
+       // remove but don't verify parity. (pType = 2)
+       size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117);
+       if ( size <= 103 ) {
+               if (g_debugMode) PrintAndLog("Error removeParity:: %d", size);
+               return 0;
+       }
+       if (g_debugMode) {
+               char *bin = sprint_bin_break(BitStream,size,16);
+               PrintAndLog("DEBUG BinStream:\n%s",bin);
+       }
+       PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:");
+       if (g_debugMode) PrintAndLog("Start marker %d;   Size %d", preambleIndex, size);
+
+       //got a good demod
+       uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32);
+       uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10);
+       uint8_t dataBlockBit = BitStream[48];
+       uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14);
+       uint8_t animalBit = BitStream[63];
+       uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16);
+       uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24);
+
+       uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32);
+       uint8_t raw[8];
+       num_to_bytes(rawid, 8, raw);
+
+       if (g_debugMode) PrintAndLog("Raw ID Hex: %s", sprint_hex(raw,8));
+
+       uint16_t calcCrc = crc16_ccitt_kermit(raw, 8);
+       PrintAndLog("Animal ID:     %04u-%012llu", countryCode, NationalCode);
+       PrintAndLog("National Code: %012llu", NationalCode);
+       PrintAndLog("CountryCode:   %04u", countryCode);
+       PrintAndLog("Extended Data: %s", dataBlockBit ? "True" : "False");
+       PrintAndLog("reserved Code: %u", reservedCode);
+       PrintAndLog("Animal Tag:    %s", animalBit ? "True" : "False");
+       PrintAndLog("CRC:           0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed");
+       PrintAndLog("Extended:      0x%X\n", extended);
+       
+       return 1;
+}
+
+
 //by marshmellow
 //attempt to psk1 demod graph buffer
 int PSKDemod(const char *Cmd, bool verbose)
@@ -1434,12 +1546,12 @@ int PSKDemod(const char *Cmd, bool verbose)
                clk=0;
        }
        if (invert != 0 && invert != 1) {
-               if (verbose) PrintAndLog("Invalid argument: %s", Cmd);
+               if (g_debugMode || verbose) PrintAndLog("Invalid argument: %s", Cmd);
                return 0;
        }
        uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
        size_t BitLen = getFromGraphBuf(BitStream);
-       if (BitLen==0) return -1;
+       if (BitLen==0) return 0;
        uint8_t carrier=countFC(BitStream, BitLen, 0);
        if (carrier!=2 && carrier!=4 && carrier!=8){
                //invalid carrier
@@ -2165,6 +2277,7 @@ static command_t CommandTable[] =
        {"buffclear",       CmdBuffClear,       1, "Clear sample buffer and graph window"},
        {"dec",             CmdDec,             1, "Decimate samples"},
        {"detectclock",     CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
+       {"fdxbdemod",       CmdFDXBdemodBI    , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"},
        {"fskawiddemod",    CmdFSKdemodAWID,    1, "Demodulate an AWID FSK tag from GraphBuffer"},
        //{"fskfcdetect",   CmdFSKfcDetect,     1, "Try to detect the Field Clock of an FSK wave"},
        {"fskhiddemod",     CmdFSKdemodHID,     1, "Demodulate a HID FSK tag from GraphBuffer"},
@@ -2182,7 +2295,7 @@ static command_t CommandTable[] =
        {"manrawdecode",    Cmdmandecoderaw,    1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"},
        {"norm",            CmdNorm,            1, "Normalize max/min to +/-128"},
        {"plot",            CmdPlot,            1, "Show graph window (hit 'h' in window for keystroke help)"},
-       {"printdemodbuffer",CmdPrintDemodBuff,  1, "[x] -- print the data in the DemodBuffer - 'x' for hex output"},
+       {"printdemodbuffer",CmdPrintDemodBuff,  1, "[x] [o] <offset> -- print the data in the DemodBuffer - 'x' for hex output"},
        {"pskindalademod",  CmdIndalaDecode,    1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"},
        {"psknexwatchdemod",CmdPSKNexWatch,     1, "Demodulate a NexWatch tag (nexkey, quadrakey) (PSK1) from GraphBuffer"},
        {"rawdemod",        CmdRawDemod,        1, "[modulation] ... <options> -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"},  
index c62307368d6ef3965a3d7dad3ae2842b9afc36d5..fcc51a6bee079068127950e46a2fde9dd9edf3bf 100644 (file)
@@ -27,6 +27,7 @@ int CmdBitsamples(const char *Cmd);
 int CmdBuffClear(const char *Cmd);
 int CmdDec(const char *Cmd);
 int CmdDetectClockRate(const char *Cmd);
+int CmdFDXBdemodBI(const char *Cmd);
 int CmdFSKdemodAWID(const char *Cmd);
 int CmdFSKdemodHID(const char *Cmd);
 int CmdFSKdemodIO(const char *Cmd);
index 16f7bb0f39f661c180723bd0c52bd1306407f8bd..fc6127c2d2dadef666eea5bb3fa0f007bacb73a0 100644 (file)
@@ -378,7 +378,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
                        oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
                }
                uint8_t parityBits = parityBytes[j>>3];
-               if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+               if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
                        snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
 
                } else {
index 525ffcc63d1d62a79c14c1845ff8099fe3390b06..496267cd47a55da826aadb888d5516cddb474db8 100644 (file)
 
 static int CmdHelp(const char *Cmd);
 
-int CmdHF14BDemod(const char *Cmd)
-{
-  int i, j, iold;
-  int isum, qsum;
-  int outOfWeakAt;
-  bool negateI, negateQ;
-
-  uint8_t data[256];
-  int dataLen = 0;
-
-  // As received, the samples are pairs, correlations against I and Q
-  // square waves. So estimate angle of initial carrier (or just
-  // quadrant, actually), and then do the demod.
-
-  // First, estimate where the tag starts modulating.
-  for (i = 0; i < GraphTraceLen; i += 2) {
-    if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) {
-      break;
-    }
-  }
-  if (i >= GraphTraceLen) {
-    PrintAndLog("too weak to sync");
-    return 0;
-  }
-  PrintAndLog("out of weak at %d", i);
-  outOfWeakAt = i;
-
-  // Now, estimate the phase in the initial modulation of the tag
-  isum = 0;
-  qsum = 0;
-  for (; i < (outOfWeakAt + 16); i += 2) {
-    isum += GraphBuffer[i + 0];
-    qsum += GraphBuffer[i + 1];
-  }
-  negateI = (isum < 0);
-  negateQ = (qsum < 0);
-
-  // Turn the correlation pairs into soft decisions on the bit.
-  j = 0;
-  for (i = 0; i < GraphTraceLen / 2; i++) {
-    int si = GraphBuffer[j];
-    int sq = GraphBuffer[j + 1];
-    if (negateI) si = -si;
-    if (negateQ) sq = -sq;
-    GraphBuffer[i] = si + sq;
-    j += 2;
-  }
-  GraphTraceLen = i;
-
-  i = outOfWeakAt / 2;
-  while (GraphBuffer[i] > 0 && i < GraphTraceLen)
-    i++;
-  if (i >= GraphTraceLen) goto demodError;
-
-  iold = i;
-  while (GraphBuffer[i] < 0 && i < GraphTraceLen)
-    i++;
-  if (i >= GraphTraceLen) goto demodError;
-  if ((i - iold) > 23) goto demodError;
-
-  PrintAndLog("make it to demod loop");
-
-  for (;;) {
-    iold = i;
-    while (GraphBuffer[i] >= 0 && i < GraphTraceLen)
-      i++;
-    if (i >= GraphTraceLen) goto demodError;
-    if ((i - iold) > 6) goto demodError;
-
-    uint16_t shiftReg = 0;
-    if (i + 20 >= GraphTraceLen) goto demodError;
-
-    for (j = 0; j < 10; j++) {
-      int soft = GraphBuffer[i] + GraphBuffer[i + 1];
-
-      if (abs(soft) < (abs(isum) + abs(qsum)) / 20) {
-        PrintAndLog("weak bit");
-      }
-
-      shiftReg >>= 1;
-      if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
-        shiftReg |= 0x200;
-      }
-
-      i+= 2;
-    }
-
-    if ((shiftReg & 0x200) && !(shiftReg & 0x001))
-    {
-      // valid data byte, start and stop bits okay
-      PrintAndLog("   %02x", (shiftReg >> 1) & 0xff);
-      data[dataLen++] = (shiftReg >> 1) & 0xff;
-      if (dataLen >= sizeof(data)) {
-        return 0;
-      }
-    } else if (shiftReg == 0x000) {
-      // this is EOF
-      break;
-    } else {
-      goto demodError;
-    }
-  }
-
-  uint8_t first, second;
-  ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
-  PrintAndLog("CRC: %02x %02x (%s)\n", first, second,
-    (first == data[dataLen-2] && second == data[dataLen-1]) ?
-      "ok" : "****FAIL****");
-
-  RepaintGraphWindow();
-  return 0;
-
-demodError:
-  PrintAndLog("demod error");
-  RepaintGraphWindow();
-  return 0;
-}
-
 int CmdHF14BList(const char *Cmd)
 {
        PrintAndLog("Deprecated command, use 'hf list 14b' instead");
 
        return 0;
 }
-int CmdHF14BRead(const char *Cmd)
-{
-  UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}};
-  SendCommand(&c);
-  return 0;
-}
-
-int CmdHF14Sim(const char *Cmd)
-{
-  UsbCommand c={CMD_SIMULATE_TAG_ISO_14443};
-  SendCommand(&c);
-  return 0;
-}
 
-int CmdHFSimlisten(const char *Cmd)
+int CmdHF14BSim(const char *Cmd)
 {
-  UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN};
+  UsbCommand c={CMD_SIMULATE_TAG_ISO_14443B};
   SendCommand(&c);
   return 0;
 }
 
 int CmdHF14BSnoop(const char *Cmd)
 {
-  UsbCommand c = {CMD_SNOOP_ISO_14443};
+  UsbCommand c = {CMD_SNOOP_ISO_14443B};
   SendCommand(&c);
   return 0;
 }
@@ -288,7 +157,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
         if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
             recv = resp.d.asBytes;
             PrintAndLog("received %i octets",resp.arg[0]);
-            if(!resp.arg[0])
+            if(resp.arg[0] == 0)
                 return 0;
             hexout = (char *)malloc(resp.arg[0] * 3 + 1);
             if (hexout != NULL) {
@@ -298,11 +167,13 @@ int CmdHF14BCmdRaw (const char *cmd) {
                 }
                 PrintAndLog("%s", hexout);
                 free(hexout);
-                ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second);
-                if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) {
-                    PrintAndLog("CRC OK");
-                } else {
-                    PrintAndLog("CRC failed");
+                               if (resp.arg[0] > 2) {
+                                       ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second);
+                                       if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) {
+                                               PrintAndLog("CRC OK");
+                                       } else {
+                                               PrintAndLog("CRC failed");
+                                       }
                 }
             } else {
                 PrintAndLog("malloc failed your client has low memory?");
@@ -385,12 +256,9 @@ int CmdHF14BWrite( const char *Cmd){
 static command_t CommandTable[] = 
 {
   {"help",        CmdHelp,        1, "This help"},
-  {"demod",       CmdHF14BDemod,  1, "Demodulate ISO14443 Type B from tag"},
   {"list",        CmdHF14BList,   0, "[Deprecated] List ISO 14443b history"},
-  {"read",        CmdHF14BRead,   0, "Read HF tag (ISO 14443)"},
-  {"sim",         CmdHF14Sim,     0, "Fake ISO 14443 tag"},
-  {"simlisten",   CmdHFSimlisten, 0, "Get HF samples as fake tag"},
-  {"snoop",       CmdHF14BSnoop,  0, "Eavesdrop ISO 14443"},
+  {"sim",         CmdHF14BSim,    0, "Fake ISO 14443B tag"},
+  {"snoop",       CmdHF14BSnoop,  0, "Eavesdrop ISO 14443B"},
   {"sri512read",  CmdSri512Read,  0, "Read contents of a SRI512 tag"},
   {"srix4kread",  CmdSrix4kRead,  0, "Read contents of a SRIX4K tag"},
   {"raw",         CmdHF14BCmdRaw, 0, "Send raw hex data to tag"},
index 3286ceb9cce45a2f9d9738219347044db63a303a..e9c63f20b02f7f88fae741f4e24780a763bff910 100644 (file)
@@ -9,7 +9,7 @@
 //-----------------------------------------------------------------------------
 
 #include "util.h"
-//#include "proxusb.h"
+
 #include "proxmark3.h"
 #include "ui.h"
 #include "cmdparser.h"
@@ -29,9 +29,9 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
        unsigned int n = 0;
        // delay between requests
        unsigned int d = 0;
-       
+
        sscanf(Cmd, "%u %u %u", &m, &n, &d);
-       
+
        // values are expected to be > 0
        m = m > 0 ? m : 1;
        n = n > 0 ? n : 1;
@@ -44,7 +44,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
                UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}};
                SendCommand(&c);
                UsbCommand resp;
-    
+
                WaitForResponse(CMD_ACK,&resp);
 
                // check if command failed
@@ -68,13 +68,123 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
        return 1;
 }
 
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////The commands lie below here/////////////////////////////////////////////////////////////////////////////////////////
+
+// perform the PACE protocol by replaying APDUs
+int CmdHFEPAPACEReplay(const char *Cmd)
+{
+       // the 4 APDUs which are replayed + their lengths
+       uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75];
+       uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0};
+       // pointers to the arrays to be able to iterate
+       uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu};
+
+       // usage message
+       static const char const *usage_msg =
+               "Please specify 5 APDUs separated by spaces. "
+               "Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D";
+
+       // Proxmark response
+       UsbCommand resp;
+
+       int skip = 0, skip_add = 0, scan_return = 0;
+       // for each APDU
+       for (int i = 0; i < sizeof(apdu_lengths); i++) {
+               // scan to next space or end of string
+               while (Cmd[skip] != ' ' && Cmd[skip] != '\0') {
+                       // convert
+                       scan_return = sscanf(Cmd + skip, "%2X%n",
+                                            (unsigned int *) (apdus[i] + apdu_lengths[i]),
+                                            &skip_add);
+                       if (scan_return < 1) {
+                               PrintAndLog((char *)usage_msg);
+                               PrintAndLog("Not enough APDUs! Try again!");
+                               return 0;
+                       }
+                       skip += skip_add;
+            apdu_lengths[i]++;
+               }
+
+               // break on EOF
+               if (Cmd[skip] == '\0') {
+                       if (i < sizeof(apdu_lengths) - 1) {
+
+                               PrintAndLog((char *)usage_msg);
+                               return 0;
+                       }
+                       break;
+               }
+               // skip the space
+               skip++;
+       }
+
+       // transfer the APDUs to the Proxmark
+       UsbCommand usb_cmd;
+       usb_cmd.cmd = CMD_EPA_PACE_REPLAY;
+       for (int i = 0; i < sizeof(apdu_lengths); i++) {
+               // APDU number
+               usb_cmd.arg[0] = i + 1;
+               // transfer the APDU in several parts if necessary
+               for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) {
+                       // offset into the APDU
+                       usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes);
+                       // amount of data in this packet
+                       int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes));
+                       if (packet_length > sizeof(usb_cmd.d.asBytes)) {
+                               packet_length = sizeof(usb_cmd.d.asBytes);
+                       }
+                       usb_cmd.arg[2] = packet_length;
+
+                       memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)),
+                              apdus[i] + (j * sizeof(usb_cmd.d.asBytes)),
+                              packet_length);
+                       SendCommand(&usb_cmd);
+                       WaitForResponse(CMD_ACK, &resp);
+                       if (resp.arg[0] != 0) {
+                               PrintAndLog("Transfer of APDU #%d Part %d failed!", i, j);
+                               return 0;
+                       }
+               }
+       }
+
+       // now perform the replay
+       usb_cmd.arg[0] = 0;
+       SendCommand(&usb_cmd);
+       WaitForResponse(CMD_ACK, &resp);
+       if (resp.arg[0] != 0) {
+               PrintAndLog("\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]);
+               PrintAndLog("Measured times:");
+               PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
+               PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
+               PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
+               PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
+               PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
+       } else {
+               PrintAndLog("PACE replay successfull!");
+               PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
+               PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
+               PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
+               PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
+               PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
+       }
+
+
+       return 1;
+}
+
+////////////////////////////////The new commands lie above here/////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 // UI-related stuff
 
-static const command_t CommandTable[] = 
+static const command_t CommandTable[] =
 {
   {"help",    CmdHelp,                   1, "This help"},
   {"cnonces", CmdHFEPACollectPACENonces, 0,
               "<m> <n> <d> Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"},
+  {"preplay", CmdHFEPAPACEReplay,        0,
+   "<mse> <get> <map> <pka> <ma> Perform PACE protocol by replaying given APDUs"},
   {NULL, NULL, 0, NULL}
 };
 
@@ -92,4 +202,4 @@ int CmdHFEPA(const char *Cmd)
        // parse
   CmdsParse(CommandTable, Cmd);
   return 0;
-}
\ No newline at end of file
+}
index 2b5a5b87965dd7b36e283e9f94fe876f2e740dc7..5abda060d8e4e40ae83f71977e4d864ad39dfaff 100644 (file)
@@ -1750,10 +1750,13 @@ int CmdHF14AMfCSave(const char *Cmd) {
                        // get filename\r
                        if (mfCGetBlock(0, buf, CSETBLOCK_SINGLE_OPER)) {\r
                                PrintAndLog("Cant get block: %d", 0);\r
-                               return 1;\r
+                               len = sprintf(fnameptr, "dump");\r
+                               fnameptr += len;\r
+                       }\r
+                       else {\r
+                               for (j = 0; j < 7; j++, fnameptr += 2)\r
+                                       sprintf(fnameptr, "%02x", buf[j]); \r
                        }\r
-                       for (j = 0; j < 7; j++, fnameptr += 2)\r
-                               sprintf(fnameptr, "%02x", buf[j]); \r
                } else {\r
                        memcpy(filename, Cmd, len);\r
                        fnameptr += len;\r
index 191032984929b77e34a998b0b1b5bdfc29c74fba..25a073d34440b2de98b3c56d67597dbc2df14111 100644 (file)
 #include "protocols.h"
 #include "data.h"
 
-#define MAX_UL_BLOCKS     0x0f
-#define MAX_ULC_BLOCKS    0x2b
-#define MAX_ULEV1a_BLOCKS 0x13
-#define MAX_ULEV1b_BLOCKS 0x28
-#define MAX_NTAG_203      0x29
-#define MAX_NTAG_210      0x13
-#define MAX_NTAG_212      0x28
-#define MAX_NTAG_213      0x2c
-#define MAX_NTAG_215      0x86
-#define MAX_NTAG_216      0xe6
+#define MAX_UL_BLOCKS      0x0f
+#define MAX_ULC_BLOCKS     0x2b
+#define MAX_ULEV1a_BLOCKS  0x13
+#define MAX_ULEV1b_BLOCKS  0x28
+#define MAX_NTAG_203       0x29
+#define MAX_NTAG_210       0x13
+#define MAX_NTAG_212       0x28
+#define MAX_NTAG_213       0x2c
+#define MAX_NTAG_215       0x86
+#define MAX_NTAG_216       0xe6
+#define MAX_MY_D_NFC       0xff
+#define MAX_MY_D_MOVE      0x25
+#define MAX_MY_D_MOVE_LEAN 0x0f
 
 #define KEYS_3DES_COUNT 7
 uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = {
@@ -54,17 +57,18 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = {
        {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) 
 };
 
-#define MAX_UL_TYPES 16
-uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203,
-           NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC};
+#define MAX_UL_TYPES 18
+uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203,
+           NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL};
 
 uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS,
            MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213,
-           MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS};
+           MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS};
 
 
 static int CmdHelp(const char *Cmd);
 
+// get version nxp product type 
 char *getProductTypeStr( uint8_t id){
 
        static char buf[20];
@@ -102,17 +106,20 @@ char *getUlev1CardSizeStr( uint8_t fsize ){
 
 static void ul_switch_on_field(void) {
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
+       clearCommandBuffer();
        SendCommand(&c);
 }
 
 void ul_switch_off_field(void) {
        UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
+       clearCommandBuffer();
        SendCommand(&c);
 }
 
 static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength ) {
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC, cmdlen, 0}};
        memcpy(c.d.asBytes, cmd, cmdlen);
+       clearCommandBuffer();
        SendCommand(&c);
        UsbCommand resp;
        if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
@@ -129,6 +136,7 @@ static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response,
                c.arg[0] |= ISO14A_APPEND_CRC;
 
        memcpy(c.d.asBytes, cmd, cmdlen);       
+       clearCommandBuffer();
        SendCommand(&c);
        UsbCommand resp;
        if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
@@ -193,6 +201,7 @@ static int ulc_authentication( uint8_t *key, bool switch_off_field ){
 
        UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}};
        memcpy(c.d.asBytes, key, 16);
+       clearCommandBuffer();
        SendCommand(&c);
        UsbCommand resp;
        if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0;
@@ -267,6 +276,38 @@ static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){
        return len;
 }
 
+
+// Fudan check checks for which error is given for a command with incorrect crc
+// NXP UL chip responds with 01, fudan 00.
+// other possible checks:
+//  send a0 + crc 
+//  UL responds with 00, fudan doesn't respond
+//  or
+//  send a200 + crc
+//  UL doesn't respond, fudan responds with 00
+//  or
+//  send 300000 + crc (read with extra byte(s))
+//  UL responds with read of page 0, fudan doesn't respond.
+//
+// make sure field is off before calling this function
+static int ul_fudan_check( void ){
+       iso14a_card_select_t card;
+       if ( !ul_select(&card) ) 
+               return UL_ERROR;
+
+       UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT, 4, 0}};
+
+       uint8_t cmd[4] = {0x30,0x00,0x02,0xa7}; //wrong crc on purpose  should be 0xa8
+       memcpy(c.d.asBytes, cmd, 4);
+       clearCommandBuffer();
+       SendCommand(&c);
+       UsbCommand resp;
+       if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return UL_ERROR;
+       if (resp.arg[0] != 1) return UL_ERROR;
+
+       return (!resp.d.asBytes[0]) ? FUDAN_UL : UL; //if response == 0x00 then Fudan, else Genuine NXP
+}
+
 static int ul_print_default( uint8_t *data){
 
        uint8_t uid[7];
@@ -279,13 +320,13 @@ static int ul_print_default( uint8_t *data){
        uid[6] = data[7];
 
        PrintAndLog("       UID : %s ", sprint_hex(uid, 7));
-       PrintAndLog("    UID[0] : %02X, Manufacturer: %s",  uid[0], getTagInfo(uid[0]) );
-       if ( uid[0] == 0x05 ) {
+       PrintAndLog("    UID[0] : %02X, %s",  uid[0], getTagInfo(uid[0]) );
+       if ( uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2 ) { // is infineon and 66RxxP
                uint8_t chip = (data[8] & 0xC7); // 11000111  mask, bit 3,4,5 RFU
                switch (chip){
-                       case 0xc2: PrintAndLog("   IC type : SLE 66R04P"); break;
-                       case 0xc4: PrintAndLog("   IC type : SLE 66R16P"); break;
-                       case 0xc6: PrintAndLog("   IC type : SLE 66R32P"); break;
+                       case 0xc2: PrintAndLog("   IC type : SLE 66R04P 770 Bytes"); break; //77 pages
+                       case 0xc4: PrintAndLog("   IC type : SLE 66R16P 2560 Bytes"); break; //256 pages
+                       case 0xc6: PrintAndLog("   IC type : SLE 66R32P 5120 Bytes"); break; //512 pages /2 sectors
                }
        }
        // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 
@@ -371,13 +412,17 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){
        else if ( tagtype & NTAG_I2C_2K )       
                PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD");
        else if ( tagtype & MY_D )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer);
        else if ( tagtype & MY_D_NFC )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer);
        else if ( tagtype & MY_D_MOVE )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer);
        else if ( tagtype & MY_D_MOVE_NFC )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer);
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer);
+       else if ( tagtype & MY_D_MOVE_LEAN )
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer);
+       else if ( tagtype & FUDAN_UL )
+               PrintAndLog("%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
        else
                PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype);
        return 0;
@@ -611,13 +656,20 @@ uint32_t GetHF14AMfU_Type(void){
                                ul_switch_off_field();
                        }
                }
+               if (tagtype & UL) {
+                       tagtype = ul_fudan_check(); 
+                       ul_switch_off_field();
+               }
        } else {
+               ul_switch_off_field();
                // Infinition MY-D tests   Exam high nibble 
                uint8_t nib = (card.uid[1] & 0xf0) >> 4;
                switch ( nib ){
-                       case 1: tagtype =  MY_D; break;
-                       case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two
-                       case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two
+                       // case 0: tagtype =  SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
+                       case 1: tagtype =  MY_D; break; //or SLE 66RxxS ... up to 512 pages of 8 user bytes...
+                       case 2: tagtype = (MY_D_NFC); break; //or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
+                       case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
+                       case 7: tagtype =  MY_D_MOVE_LEAN; break; //or SLE 66R01L  // 16 pages of 4 bytes
                }
        }
 
@@ -839,105 +891,239 @@ int CmdHF14AMfUInfo(const char *Cmd){
 }
 
 //
-//  Mifare Ultralight Write Single Block
+//  Write Single Block
 //
 int CmdHF14AMfUWrBl(const char *Cmd){
-       uint8_t blockNo    = -1;
-       bool chinese_card  = FALSE;
-       uint8_t bldata[16] = {0x00};
-       UsbCommand resp;
 
-       char cmdp = param_getchar(Cmd, 0);
-       if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
-               PrintAndLog("Usage:  hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
-               PrintAndLog("       [block number]");
-               PrintAndLog("       [block data] - (8 hex symbols)");
-               PrintAndLog("       [w] - Chinese magic ultralight tag");
-               PrintAndLog("");
-               PrintAndLog("        sample: hf mfu wrbl 0 01020304");
-               PrintAndLog("");                
-               return 0;
-       }       
-       
-       blockNo = param_get8(Cmd, 0);
+       int blockNo = -1;
+       bool errors = false;
+       bool hasAuthKey = false;
+       bool hasPwdKey = false;
+       bool swapEndian = false;
 
-       if (blockNo > MAX_UL_BLOCKS){
-               PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
-               return 1;
+       uint8_t cmdp = 0;
+       uint8_t keylen = 0;
+       uint8_t blockdata[20] = {0x00};
+       uint8_t data[16] = {0x00};
+       uint8_t authenticationkey[16] = {0x00};
+       uint8_t *authKeyPtr = authenticationkey;
+
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+                       case 'h':
+                       case 'H':
+                               return usage_hf_mfu_wrbl();
+                       case 'k':
+                       case 'K':
+                               // EV1/NTAG size key
+                               keylen = param_gethex(Cmd, cmdp+1, data, 8);
+                               if ( !keylen ) {
+                                       memcpy(authenticationkey, data, 4);
+                                       cmdp += 2;
+                                       hasPwdKey = true;
+                                       break;
+                               }
+                               // UL-C size key        
+                               keylen = param_gethex(Cmd, cmdp+1, data, 32);
+                               if (!keylen){
+                                       memcpy(authenticationkey, data, 16);
+                                       cmdp += 2;
+                                       hasAuthKey = true;
+                                       break;
+                               }
+                               PrintAndLog("\nERROR: Key is incorrect length\n");
+                               errors = true; 
+                               break;
+                       case 'b':
+                       case 'B':
+                               blockNo = param_get8(Cmd, cmdp+1);
+                               if (blockNo < 0) {
+                                       PrintAndLog("Wrong block number");
+                                       errors = true;
+                               }
+                               cmdp += 2;
+                               break;
+                       case 'l':
+                       case 'L':
+                               swapEndian = true;
+                               cmdp++; 
+                               break;
+                       case 'd':
+                       case 'D':
+                               if ( param_gethex(Cmd, cmdp+1, blockdata, 8) ) {
+                                       PrintAndLog("Block data must include 8 HEX symbols");
+                                       errors = true;
+                                       break;
+                               }
+                               cmdp += 2;
+                               break;
+                       default:
+                               PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                               errors = true;
+                               break;
+               }
+               //Validations
+               if(errors) return usage_hf_mfu_wrbl();
        }
-       
-       if (param_gethex(Cmd, 1, bldata, 8)) {
-               PrintAndLog("Block data must include 8 HEX symbols");
-               return 1;
+
+       if ( blockNo == -1 ) return usage_hf_mfu_wrbl();
+       // starting with getting tagtype
+       TagTypeUL_t tagtype = GetHF14AMfU_Type();
+       if (tagtype == UL_ERROR) return -1;
+
+       uint8_t maxblockno = 0;
+       for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){
+               if (tagtype & UL_TYPES_ARRAY[idx])
+                       maxblockno = UL_MEMORY_ARRAY[idx];
        }
-       
-       if (strchr(Cmd,'w') != 0  || strchr(Cmd,'W') != 0 ) {
-               chinese_card = TRUE; 
+       if (blockNo > maxblockno){
+               PrintAndLog("block number too large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
+               return usage_hf_mfu_wrbl();
        }
-       
-       if ( blockNo <= 3) {
-               if (!chinese_card){
-                       PrintAndLog("Access Denied");
-               } else {
-                       PrintAndLog("--specialblock no:%02x", blockNo);
-                       PrintAndLog("--data: %s", sprint_hex(bldata, 4));
-                       UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
-                       memcpy(d.d.asBytes,bldata, 4);
-                       SendCommand(&d);
-                       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                               uint8_t isOK  = resp.arg[0] & 0xff;
-                               PrintAndLog("isOk:%02x", isOK);
-                       } else {
-                               PrintAndLog("Command execute timeout");
-                       }  
-               }
+
+       // Swap endianness 
+       if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
+       if (swapEndian && hasPwdKey)  authKeyPtr = SwapEndian64(authenticationkey, 4, 4);
+
+       if ( blockNo <= 3)
+               PrintAndLog("Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
+       else
+               PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
+
+       //Send write Block
+       UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
+       memcpy(c.d.asBytes,blockdata,4);
+
+       if ( hasAuthKey ) {
+               c.arg[1] = 1;
+               memcpy(c.d.asBytes+4,authKeyPtr,16);
+       }
+       else if ( hasPwdKey ) {
+               c.arg[1] = 2;
+               memcpy(c.d.asBytes+4,authKeyPtr,4);
+       }
+
+       clearCommandBuffer();
+       SendCommand(&c);
+       UsbCommand resp;
+       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+               uint8_t isOK  = resp.arg[0] & 0xff;
+               PrintAndLog("isOk:%02x", isOK);
        } else {
-               PrintAndLog("--block no:%02x", blockNo);
-               PrintAndLog("--data: %s", sprint_hex(bldata, 4));               
-               UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
-               memcpy(e.d.asBytes,bldata, 4);
-               SendCommand(&e);
-               if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                       uint8_t isOK  = resp.arg[0] & 0xff;
-                       PrintAndLog("isOk:%02x", isOK);
-               } else {
-                       PrintAndLog("Command execute timeout");
-               }
+               PrintAndLog("Command execute timeout");
        }
+
        return 0;
 }
-
 //
-//  Mifare Ultralight Read Single Block
+//  Read Single Block
 //
 int CmdHF14AMfURdBl(const char *Cmd){
 
-       UsbCommand resp;
-       uint8_t blockNo = -1;   
-       char cmdp = param_getchar(Cmd, 0);
-       
-       if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {    
-               PrintAndLog("Usage:  hf mfu rdbl <block number>");
-               PrintAndLog("        sample: hfu mfu rdbl 0");
-               return 0;
+       int blockNo = -1;       
+       bool errors = false;
+       bool hasAuthKey = false;
+       bool hasPwdKey = false;
+       bool swapEndian = false;
+       uint8_t cmdp = 0;
+       uint8_t keylen = 0;
+       uint8_t data[16] = {0x00};
+       uint8_t authenticationkey[16] = {0x00};
+       uint8_t *authKeyPtr = authenticationkey;
+
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+                       case 'h':
+                       case 'H':
+                               return usage_hf_mfu_rdbl();
+                       case 'k':
+                       case 'K':
+                               // EV1/NTAG size key
+                               keylen = param_gethex(Cmd, cmdp+1, data, 8);
+                               if ( !keylen ) {
+                                       memcpy(authenticationkey, data, 4);
+                                       cmdp += 2;
+                                       hasPwdKey = true;
+                                       break;
+                               }
+                               // UL-C size key        
+                               keylen = param_gethex(Cmd, cmdp+1, data, 32);
+                               if (!keylen){
+                                       memcpy(authenticationkey, data, 16);
+                                       cmdp += 2;
+                                       hasAuthKey = true;
+                                       break;
+                               }
+                               PrintAndLog("\nERROR: Key is incorrect length\n");
+                               errors = true; 
+                               break;
+                       case 'b':
+                       case 'B':
+                               blockNo = param_get8(Cmd, cmdp+1);
+                               if (blockNo < 0) {
+                                       PrintAndLog("Wrong block number");
+                                       errors = true;
+                               }
+                               cmdp += 2;
+                               break;
+                       case 'l':
+                       case 'L':
+                               swapEndian = true;
+                               cmdp++;
+                               break;
+                       default:
+                               PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                               errors = true;
+                               break;
+               }
+               //Validations
+               if(errors) return usage_hf_mfu_rdbl();
        }
 
-       blockNo = param_get8(Cmd, 0);
+       if ( blockNo == -1 ) return usage_hf_mfu_rdbl();
+       // start with getting tagtype
+       TagTypeUL_t tagtype = GetHF14AMfU_Type();
+       if (tagtype == UL_ERROR) return -1;
 
-       if (blockNo > MAX_UL_BLOCKS){
-               PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight");
-               return 1;
+       uint8_t maxblockno = 0;
+       for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){
+               if (tagtype & UL_TYPES_ARRAY[idx])
+                       maxblockno = UL_MEMORY_ARRAY[idx];
+       }
+       if (blockNo > maxblockno){
+               PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
+               return usage_hf_mfu_rdbl();
        }
 
-       UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
-       SendCommand(&c);
+       // Swap endianness 
+       if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
+       if (swapEndian && hasPwdKey)  authKeyPtr = SwapEndian64(authenticationkey, 4, 4);
 
+       //Read Block
+       UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
+       if ( hasAuthKey ){
+               c.arg[1] = 1;
+               memcpy(c.d.asBytes,authKeyPtr,16);
+       }
+       else if ( hasPwdKey ) {
+               c.arg[1] = 2;
+               memcpy(c.d.asBytes,authKeyPtr,4);
+       }
 
+       clearCommandBuffer();
+       SendCommand(&c);
+       UsbCommand resp;
        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
                uint8_t isOK = resp.arg[0] & 0xff;
                if (isOK) {
                        uint8_t *data = resp.d.asBytes;
-                       PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
+                       PrintAndLog("\nBlock#  | Data        | Ascii");
+                       PrintAndLog("-----------------------------");
+                       PrintAndLog("%02d/0x%02X | %s| %.4s\n", blockNo, blockNo, sprint_hex(data, 4), data);
                }
                else {
                        PrintAndLog("Failed reading block: (%02x)", isOK);
@@ -945,7 +1131,6 @@ int CmdHF14AMfURdBl(const char *Cmd){
        } else {
                PrintAndLog("Command execute time-out");
        }
-
        return 0;
 }
 
@@ -988,6 +1173,34 @@ int usage_hf_mfu_dump(void) {
        return 0;
 }
 
+int usage_hf_mfu_rdbl(void) {
+       PrintAndLog("Read a block and print. It autodetects card type.\n");     
+       PrintAndLog("Usage:  hf mfu rdbl b <block number> k <key> l\n");
+       PrintAndLog("  Options:");
+       PrintAndLog("  b <no>  : block to read");
+       PrintAndLog("  k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+       PrintAndLog("  l       : (optional) swap entered key's endianness");    
+       PrintAndLog("");
+       PrintAndLog("   sample : hf mfu rdbl b 0");
+       PrintAndLog("          : hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF");
+       PrintAndLog("          : hf mfu rdbl b 0 k AABBCCDDD\n");
+       return 0;
+}
+
+int usage_hf_mfu_wrbl(void) {
+       PrintAndLog("Write a block. It autodetects card type.\n");              
+       PrintAndLog("Usage:  hf mfu wrbl b <block number> d <data> k <key> l\n");
+       PrintAndLog("  Options:");
+       PrintAndLog("  b <no>   : block to write");
+       PrintAndLog("  d <data> : block data - (8 hex symbols)");
+       PrintAndLog("  k <key>  : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+       PrintAndLog("  l        : (optional) swap entered key's endianness");   
+       PrintAndLog("");
+       PrintAndLog("    sample : hf mfu wrbl b 0 d 01234567");
+       PrintAndLog("           : hf mfu wrbl b 0 d 01234567 k AABBCCDDD\n");
+       return 0;
+}
+
 //
 //  Mifare Ultralight / Ultralight-C / Ultralight-EV1
 //  Read and Dump Card Contents,  using auto detection of tag size.
@@ -1079,10 +1292,10 @@ int CmdHF14AMfUDump(const char *Cmd){
        TagTypeUL_t tagtype = GetHF14AMfU_Type();
        if (tagtype == UL_ERROR) return -1;
 
-       if (!manualPages)
+       if (!manualPages) //get number of pages to read
                for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++)
                        if (tagtype & UL_TYPES_ARRAY[idx])
-                               Pages = UL_MEMORY_ARRAY[idx]+1;
+                               Pages = UL_MEMORY_ARRAY[idx]+1; //add one as maxblks starts at 0
 
        ul_print_type(tagtype, 0);
        PrintAndLog("Reading tag memory...");
@@ -1095,6 +1308,8 @@ int CmdHF14AMfUDump(const char *Cmd){
 
                memcpy(c.d.asBytes, authKeyPtr, dataLen);
        }
+
+       clearCommandBuffer();
        SendCommand(&c);
        UsbCommand resp;
        if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) {
@@ -1153,9 +1368,11 @@ int CmdHF14AMfUDump(const char *Cmd){
                }
        }
 
+       PrintAndLog("\nBlock#  | Data        |lck| Ascii");
+       PrintAndLog("---------------------------------");
        for (i = 0; i < Pages; ++i) {
                if ( i < 3 ) {
-                       PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
+                       PrintAndLog("%02d/0x%02X | %s|   | ", i+startPage, i+startPage, sprint_hex(data + i * 4, 4));
                        continue;
                }
                switch(i){
@@ -1202,8 +1419,9 @@ int CmdHF14AMfUDump(const char *Cmd){
                        case 43: tmplockbit = bit2[9]; break;  //auth1
                        default: break;
                }
-               PrintAndLog("Block %02X:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4);
+               PrintAndLog("%02d/0x%02X | %s| %d | %.4s", i+startPage, i+startPage, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4);
        }
+       PrintAndLog("---------------------------------");
 
        // user supplied filename?
        if (fileNlen < 1) {
@@ -1369,142 +1587,6 @@ int CmdTestDES(const char * cmd)
 }
 **/
 
-//
-// Ultralight C Read Single Block
-//
-int CmdHF14AMfUCRdBl(const char *Cmd)
-{
-       UsbCommand resp;
-       bool hasPwd = FALSE;
-       uint8_t blockNo = -1;
-       uint8_t key[16];
-       char cmdp = param_getchar(Cmd, 0);
-
-       if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
-               PrintAndLog("Usage:  hf mfu crdbl  <block number> <key>");
-               PrintAndLog("");
-               PrintAndLog("sample: hf mfu crdbl 0");
-               PrintAndLog("        hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF");
-               return 0;
-       }
-
-       blockNo = param_get8(Cmd, 0);
-       if (blockNo < 0) {
-               PrintAndLog("Wrong block number");
-               return 1;
-       }
-
-       if (blockNo > MAX_ULC_BLOCKS ){
-               PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C");
-               return 1;
-       } 
-       
-       // key
-       if ( strlen(Cmd) > 3){
-               if (param_gethex(Cmd, 1, key, 32)) {
-                       PrintAndLog("Key must include %d HEX symbols", 32);
-                       return 1;
-               } else {
-                       hasPwd = TRUE;
-               }       
-       }       
-
-       //Read Block
-       UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
-       if ( hasPwd ) {
-               c.arg[1] = 1;
-               memcpy(c.d.asBytes,key,16);
-       }
-       SendCommand(&c);
-
-       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-               uint8_t isOK = resp.arg[0] & 0xff;
-               if (isOK) {
-                       uint8_t *data = resp.d.asBytes;
-                       PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
-               }
-               else {
-                       PrintAndLog("Failed reading block: (%02x)", isOK);
-               }
-       } else {
-               PrintAndLog("Command execute time-out");
-       }
-       return 0;
-}
-
-//
-//  Mifare Ultralight C Write Single Block
-//
-int CmdHF14AMfUCWrBl(const char *Cmd){
-       
-       uint8_t blockNo = -1;
-       bool chinese_card = FALSE;
-       uint8_t bldata[16] = {0x00};
-       UsbCommand resp;
-
-       char cmdp = param_getchar(Cmd, 0);
-       
-       if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {    
-               PrintAndLog("Usage:  hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
-               PrintAndLog("       [block number]");
-               PrintAndLog("       [block data] - (8 hex symbols)");
-               PrintAndLog("       [w] - Chinese magic ultralight tag");
-               PrintAndLog("");
-               PrintAndLog("        sample: hf mfu cwrbl 0 01020304");
-               PrintAndLog("");
-               return 0;
-       }
-       
-       blockNo = param_get8(Cmd, 0);
-       if (blockNo > MAX_ULC_BLOCKS ){
-               PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
-               return 1;
-       }
-       
-       if (param_gethex(Cmd, 1, bldata, 8)) {
-               PrintAndLog("Block data must include 8 HEX symbols");
-               return 1;
-       }
-
-       if (strchr(Cmd,'w') != 0  || strchr(Cmd,'W') != 0 ) {
-               chinese_card = TRUE; 
-       }
-
-       if ( blockNo <= 3 ) {
-               if (!chinese_card){
-                       PrintAndLog("Access Denied");  
-                       return 1;
-               } else {
-                       PrintAndLog("--Special block no: 0x%02x", blockNo);
-                       PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
-                       UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
-                       memcpy(d.d.asBytes,bldata, 4);
-                       SendCommand(&d);
-                       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                               uint8_t isOK  = resp.arg[0] & 0xff;
-                               PrintAndLog("isOk:%02x", isOK);
-                       } else {
-                               PrintAndLog("Command execute timeout");
-                               return 1;
-                       }
-               }
-       } else {
-                       PrintAndLog("--Block no : 0x%02x", blockNo);
-                       PrintAndLog("--Data: %s", sprint_hex(bldata, 4));               
-                       UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
-                       memcpy(e.d.asBytes,bldata, 4);
-                       SendCommand(&e);
-                       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-                               uint8_t isOK  = resp.arg[0] & 0xff;
-                               PrintAndLog("isOk : %02x", isOK);
-                       } else {
-                               PrintAndLog("Command execute timeout");
-                               return 1;
-                       }
-       }
-       return 0;
-}
-
 // 
 // Mifare Ultralight C - Set password
 //
@@ -1530,6 +1612,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){
        
        UsbCommand c = {CMD_MIFAREUC_SETPWD};   
        memcpy( c.d.asBytes, pwd, 16);
+       clearCommandBuffer();
        SendCommand(&c);
 
        UsbCommand resp;
@@ -1578,6 +1661,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){
        // read block2. 
        c.cmd = CMD_MIFAREU_READBL;
        c.arg[0] = 2;
+       clearCommandBuffer();
        SendCommand(&c);
        if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
                PrintAndLog("Command execute timeout");
@@ -1595,6 +1679,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){
        c.d.asBytes[1] = uid[1];
        c.d.asBytes[2] = uid[2];
        c.d.asBytes[3] =  0x88 ^ uid[0] ^ uid[1] ^ uid[2];
+       clearCommandBuffer();
        SendCommand(&c);
        if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
                PrintAndLog("Command execute timeout");
@@ -1607,6 +1692,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){
        c.d.asBytes[1] = uid[4];
        c.d.asBytes[2] = uid[5];
        c.d.asBytes[3] = uid[6];
+       clearCommandBuffer();
        SendCommand(&c);
        if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
                PrintAndLog("Command execute timeout");
@@ -1619,6 +1705,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){
        c.d.asBytes[1] = oldblock2[1];
        c.d.asBytes[2] = oldblock2[2];
        c.d.asBytes[3] = oldblock2[3];
+       clearCommandBuffer();
        SendCommand(&c);
        if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
                PrintAndLog("Command execute timeout");
@@ -1629,10 +1716,10 @@ int CmdHF14AMfucSetUid(const char *Cmd){
 }
 
 int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
-       
+
        uint8_t iv[8] = { 0x00 };
        uint8_t block = 0x07;
-       
+
        // UL-EV1
        //04 57 b6 e2 05 3f 80 UID
        //4a f8 4b 19   PWD
@@ -1646,14 +1733,14 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
        
        uint8_t mix[8] = { 0x00 };
        uint8_t divkey[8] = { 0x00 };
-       
+
        memcpy(mix, mifarekeyA, 4);
-       
+
        mix[4] = mifarekeyA[4] ^ uid[0];
        mix[5] = mifarekeyA[5] ^ uid[1];
        mix[6] = block ^ uid[2];
        mix[7] = uid[3];
-       
+
        des3_context ctx = { 0x00 };
        des3_set2key_enc(&ctx, masterkey);
 
@@ -1672,9 +1759,9 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
        PrintAndLog("Mifare key   :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA)));
        PrintAndLog("Message      :\t %s", sprint_hex(mix, sizeof(mix)));
        PrintAndLog("Diversified key: %s", sprint_hex(divkey+1, 6));
-               
+
        PrintAndLog("\n DES version");
-       
+
        for (int i=0; i < sizeof(mifarekeyA); ++i){
                dkeyA[i] = (mifarekeyA[i] << 1) & 0xff;
                dkeyA[6] |=  ((mifarekeyA[i] >> 7) & 1) << (i+1);
@@ -1692,7 +1779,7 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
        memcpy(dmkey+8, dkeyB, 8);
        memcpy(dmkey+16, dkeyA, 8);
        memset(iv, 0x00, 8);
-       
+
        des3_set3key_enc(&ctx, dmkey);
 
        des3_crypt_cbc(&ctx  // des3_context
@@ -1735,11 +1822,9 @@ static command_t CommandTable[] =
        {"help",        CmdHelp,                        1, "This help"},
        {"dbg",         CmdHF14AMfDbg,          0, "Set default debug mode"},
        {"info",        CmdHF14AMfUInfo,        0, "Tag information"},
-       {"dump",        CmdHF14AMfUDump,        0, "Dump Ultralight / Ultralight-C tag to binary file"},
-       {"rdbl",        CmdHF14AMfURdBl,        0, "Read block  - Ultralight"},
-       {"wrbl",        CmdHF14AMfUWrBl,        0, "Write block - Ultralight"},    
-       {"crdbl",       CmdHF14AMfUCRdBl,       0, "Read block        - Ultralight C"},
-       {"cwrbl",       CmdHF14AMfUCWrBl,       0, "Write block       - Ultralight C"},
+       {"dump",        CmdHF14AMfUDump,        0, "Dump Ultralight / Ultralight-C / NTAG tag to binary file"},
+       {"rdbl",        CmdHF14AMfURdBl,        0, "Read block"},
+       {"wrbl",        CmdHF14AMfUWrBl,        0, "Write block"},
        {"cauth",       CmdHF14AMfucAuth,       0, "Authentication    - Ultralight C"},
        {"setpwd",      CmdHF14AMfucSetPwd, 1, "Set 3des password - Ultralight-C"},
        {"setuid",      CmdHF14AMfucSetUid, 1, "Set UID - MAGIC tags only"},
index 83f2840316c06d111597a80ce09a632fe1b7a21c..6c9e3ea1b66834d54b6e166c51f6e5a4d326b4c7 100644 (file)
@@ -4,25 +4,24 @@
 #ifndef CMDHFMFU_H__
 #define CMDHFMFU_H__
 
-//standard ultralight
 int CmdHF14AMfUWrBl(const char *Cmd);
 int CmdHF14AMfURdBl(const char *Cmd);
 
 //Crypto Cards
-int CmdHF14AMfUCRdBl(const char *Cmd);
-int CmdHF14AMfUCRdCard(const char *Cmd);
 int CmdHF14AMfucAuth(const char *Cmd);
 
 //general stuff
 int CmdHF14AMfUDump(const char *Cmd);
 int CmdHF14AMfUInfo(const char *Cmd);
-uint32_t GetHF14AMfU_Type(void);
 
+uint32_t GetHF14AMfU_Type(void);
 int ul_print_type(uint32_t tagtype, uint8_t spacer);
 void ul_switch_off_field(void);
 
 int usage_hf_mfu_dump(void);
 int usage_hf_mfu_info(void);
+int usage_hf_mfu_rdbl(void);
+int usage_hf_mfu_wrbl(void);
 
 int CmdHFMFUltra(const char *Cmd);
 
@@ -43,9 +42,11 @@ typedef enum TAGTYPE_UL {
        MY_D_NFC      = 0x001000,
        MY_D_MOVE     = 0x002000,
        MY_D_MOVE_NFC = 0x004000,
-       NTAG_I2C_1K   = 0x008000,
-       NTAG_I2C_2K   = 0x010000,
-       MAGIC         = 0x020000,
+       MY_D_MOVE_LEAN= 0x008000,
+       NTAG_I2C_1K   = 0x010000,
+       NTAG_I2C_2K   = 0x020000,
+       FUDAN_UL      = 0x040000,
+       MAGIC         = 0x080000,
        UL_MAGIC      = UL | MAGIC,
        UL_C_MAGIC    = UL_C | MAGIC,
        UL_ERROR      = 0xFFFFFF,
index dfbbe992a76a6a3bdeadb0d01becdc2cb7a051e5..edf029325ddbe8e353197cdbc667681e14acadc2 100644 (file)
@@ -1072,6 +1072,12 @@ int CmdLFfind(const char *Cmd)
                return 1;
        }
 
+       ans=CmdFDXBdemodBI("");
+       if (ans>0) {
+               PrintAndLog("\nValid FDX-B ID Found!");
+               return 1;
+       }
+
        ans=EM4x50Read("", false);
        if (ans>0) {
                PrintAndLog("\nValid EM4x50 ID Found!");
index c492a64d52e5c4e056202302142836a2f893ae80..eddeec5604ea68229d68088f409f2193d244259a 100644 (file)
@@ -20,6 +20,9 @@
 #include "cmdlf.h"
 #include "cmdlfem4x.h"
 #include "lfdemod.h"
+
+#define llx PRIx64
+
 char *global_em410xId;
 
 static int CmdHelp(const char *Cmd);
index d4b72b3279bbbaf0844f0703334c1d016d6c4176..b357e71c30c50e327f42cbe346475614685da428 100644 (file)
@@ -50,24 +50,24 @@ int usage_t55xx_config(){
 }\r
 int usage_t55xx_read(){\r
        PrintAndLog("Usage:  lf t55xx read <block> <password>");\r
-    PrintAndLog("     <block>, block number to read. Between 0-7");\r
-    PrintAndLog("     <password>, OPTIONAL password (8 hex characters)");\r
-    PrintAndLog("");\r
+       PrintAndLog("     <block>, block number to read. Between 0-7");\r
+       PrintAndLog("     <password>, OPTIONAL password (8 hex characters)");\r
+       PrintAndLog("");\r
        PrintAndLog("Examples:");\r
-    PrintAndLog("      lf t55xx read 0           - read data from block 0");\r
+       PrintAndLog("      lf t55xx read 0           - read data from block 0");\r
        PrintAndLog("      lf t55xx read 0 feedbeef  - read data from block 0 password feedbeef");\r
        PrintAndLog("");\r
        return 0;\r
 }\r
 int usage_t55xx_write(){\r
        PrintAndLog("Usage:  lf t55xx wr <block> <data> [password]");\r
-    PrintAndLog("     <block>, block number to read. Between 0-7");\r
+       PrintAndLog("     <block>, block number to write. Between 0-7");\r
        PrintAndLog("     <data>,  4 bytes of data to write (8 hex characters)");\r
-    PrintAndLog("     [password], OPTIONAL password 4bytes (8 hex characters)");\r
-    PrintAndLog("");\r
+       PrintAndLog("     [password], OPTIONAL password 4bytes (8 hex characters)");\r
+       PrintAndLog("");\r
        PrintAndLog("Examples:");\r
-    PrintAndLog("      lf t55xx wd 3 11223344           - write 11223344 to block 3");\r
-       PrintAndLog("      lf t55xx wd 3 11223344 feedbeef  - write 11223344 to block 3 password feedbeef");\r
+       PrintAndLog("      lf t55xx wr 3 11223344           - write 11223344 to block 3");\r
+       PrintAndLog("      lf t55xx wr 3 11223344 feedbeef  - write 11223344 to block 3 password feedbeef");\r
        PrintAndLog("");\r
        return 0;\r
 }\r
index c5b91f99783830e3274d54169aa4ae4a289f02bb..b3a7f4ec94c3e3663fc3db40fb9de301dbb1d065 100644 (file)
@@ -89,7 +89,6 @@ typedef struct {
 
 // For the 13.56 MHz tags
 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693                             0x0300
-#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443                             0x0301
 #define CMD_READ_SRI512_TAG                                               0x0303
 #define CMD_READ_SRIX4K_TAG                                               0x0304
 #define CMD_READER_ISO_15693                                              0x0310
@@ -105,9 +104,8 @@ typedef struct {
 #define CMD_SIMULATE_HITAG                                                0x0371
 #define CMD_READER_HITAG                                                  0x0372
 
-#define CMD_SIMULATE_TAG_HF_LISTEN                                        0x0380
-#define CMD_SIMULATE_TAG_ISO_14443                                        0x0381
-#define CMD_SNOOP_ISO_14443                                               0x0382
+#define CMD_SIMULATE_TAG_ISO_14443B                                       0x0381
+#define CMD_SNOOP_ISO_14443B                                              0x0382
 #define CMD_SNOOP_ISO_14443a                                              0x0383
 #define CMD_SIMULATE_TAG_ISO_14443a                                       0x0384
 #define CMD_READER_ISO_14443a                                             0x0385
index 678c745ec65cc2afd8b0583ed99ec3d74489c80f..4c7bc638319d39066227f769c4ee662720a58707 100644 (file)
@@ -59,7 +59,6 @@ local _commands = {
 
        --// For the 13.56 MHz tags
        CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 =                              0x0300,
-       CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 =                              0x0301,
        CMD_READ_SRI512_TAG =                                                0x0303,
        CMD_READ_SRIX4K_TAG =                                                0x0304,
        CMD_READER_ISO_15693 =                                               0x0310,
@@ -76,9 +75,8 @@ local _commands = {
        CMD_SIMULATE_HITAG =                                                 0x0371,
        CMD_READER_HITAG =                                                   0x0372,
 
-       CMD_SIMULATE_TAG_HF_LISTEN =                                         0x0380,
-       CMD_SIMULATE_TAG_ISO_14443 =                                         0x0381,
-       CMD_SNOOP_ISO_14443 =                                                0x0382,
+       CMD_SIMULATE_TAG_ISO_14443B =                                        0x0381,
+       CMD_SNOOP_ISO_14443B =                                               0x0382,
        CMD_SNOOP_ISO_14443a =                                               0x0383,
        CMD_SIMULATE_TAG_ISO_14443a =                                        0x0384,
        CMD_READER_ISO_14443a =                                              0x0385,
index a968fde2a90c3b2218b6e67aa005bdeec7486db6..592d0477d9f1ead73a754860e218e4d8ba2eb77d 100644 (file)
@@ -99,6 +99,32 @@ local Utils =
                end\r
                return nil\r
        end,\r
+\r
+       ------------ SHA1 hash\r
+       -- Takes a string and calculates a SHA1 hash\r
+       Sha1 = function(s)\r
+               if s == nil then return nil end\r
+               if #s == 0 then return nil end\r
+               if  type(s) == 'string' then\r
+                       local utils = require('utils')\r
+                       --local asc = utils.ConvertHexToAscii(s)\r
+                       local hash = core.sha1(s)\r
+                       return hash\r
+               end\r
+               return nil\r
+       end,\r
+       -- Takes a hex string and calculates a SHA1 hash\r
+       Sha1Hex = function(s)\r
+               if s == nil then return nil end\r
+               if #s == 0 then return nil end\r
+               if  type(s) == 'string' then\r
+                       local utils = require('utils')\r
+                       local asc = utils.ConvertHexToAscii(s)\r
+                       local hash = core.sha1(asc)\r
+                       return hash\r
+               end\r
+               return nil\r
+       end,\r
        \r
        \r
        -- input parameter is a string\r
@@ -288,4 +314,4 @@ local Utils =
 -- end\r
 \r
 }\r
-return Utils
\ No newline at end of file
+return Utils\r
index 152fd9d44335236ffe3def9237d3bb38eccb68b3..6b26ec59ca119eeae71c2cf0b132fa50566b87e4 100644 (file)
@@ -20,6 +20,7 @@
 #include "../common/iso15693tools.h"
 #include "../common/crc16.h"
 #include "../common/crc64.h"
+#include "../common/sha1.h"
 #include "aes.h"
 /**
  * The following params expected:
@@ -231,7 +232,7 @@ static int l_iso15693_crc(lua_State *L)
  Simple AES 128 cbc hook up to OpenSSL.
  params:  key, input
 */
-static int l_aes128decrypt(lua_State *L)
+static int l_aes128decrypt_cbc(lua_State *L)
 {
        //Check number of arguments
        int i;
@@ -260,7 +261,36 @@ static int l_aes128decrypt(lua_State *L)
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;// return 1 to signal one return value
 }
-static int l_aes128encrypt(lua_State *L)
+static int l_aes128decrypt_ecb(lua_State *L)
+{
+       //Check number of arguments
+       int i;
+       size_t size;
+       const char *p_key = luaL_checklstring(L, 1, &size);
+       if(size != 32)  return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
+
+       const char *p_encTxt = luaL_checklstring(L, 2, &size);
+
+       unsigned char indata[16] = {0x00};
+       unsigned char outdata[16] = {0x00};
+       unsigned char aes_key[16] = {0x00};
+
+       // convert key to bytearray and convert input to bytearray
+       for (i = 0; i < 32; i += 2) {
+               sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
+               sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
+       }
+       aes_context ctx;
+       aes_init(&ctx);
+       aes_setkey_dec(&ctx, aes_key, 128);
+       aes_crypt_ecb(&ctx, AES_DECRYPT, indata, outdata );
+
+       //Push decrypted array as a string
+       lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
+       return 1;// return 1 to signal one return value
+}
+
+static int l_aes128encrypt_cbc(lua_State *L)
 {
        //Check number of arguments
        int i;
@@ -289,6 +319,33 @@ static int l_aes128encrypt(lua_State *L)
        return 1;// return 1 to signal one return value
 }
 
+static int l_aes128encrypt_ecb(lua_State *L)
+{
+       //Check number of arguments
+       int i;
+       size_t size;
+       const char *p_key = luaL_checklstring(L, 1, &size);
+       if(size != 32)  return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
+
+       const char *p_txt = luaL_checklstring(L, 2, &size);
+
+       unsigned char indata[16] = {0x00};
+       unsigned char outdata[16] = {0x00};
+       unsigned char aes_key[16] = {0x00};
+
+       for (i = 0; i < 32; i += 2) {
+               sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]);
+               sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
+       }
+       aes_context ctx;
+       aes_init(&ctx);
+       aes_setkey_enc(&ctx, aes_key, 128);
+       aes_crypt_ecb(&ctx, AES_ENCRYPT, indata, outdata );
+       //Push encrypted array as a string
+       lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
+       return 1;// return 1 to signal one return value
+}
+
 static int l_crc16(lua_State *L)
 {
        size_t size;
@@ -321,6 +378,16 @@ static int l_crc64(lua_State *L)
        return 1;
 }
 
+static int l_sha1(lua_State *L)
+{
+       size_t size;
+       const char *p_str = luaL_checklstring(L, 1, &size);
+       unsigned char outdata[20] = {0x00};
+       sha1( (uint8_t*) p_str, size, outdata);
+       lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
+       return 1;
+}
+
 /**
  * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
  * able to do "require('foobar')" if foobar.lua is within lualibs folder.
@@ -359,10 +426,13 @@ int set_pm3_libraries(lua_State *L)
                {"clearCommandBuffer",          l_clearCommandBuffer},
                {"console",                     l_CmdConsole},
                {"iso15693_crc",                l_iso15693_crc},
-               {"aes128_decrypt",              l_aes128decrypt},
-               {"aes128_encrypt",              l_aes128encrypt},
+               {"aes128_decrypt",              l_aes128decrypt_cbc},
+               {"aes128_decrypt_ecb",          l_aes128decrypt_ecb},
+               {"aes128_encrypt",              l_aes128encrypt_cbc},
+               {"aes128_encrypt_ecb",          l_aes128encrypt_ecb},
                {"crc16",                       l_crc16},
                {"crc64",                       l_crc64},
+               {"sha1",                        l_sha1},
                {NULL, NULL}
        };
 
diff --git a/client/scripts/didump.lua b/client/scripts/didump.lua
new file mode 100644 (file)
index 0000000..2386d42
--- /dev/null
@@ -0,0 +1,473 @@
+local cmds = require('commands')
+local getopt = require('getopt')
+local utils = require('utils')
+local lib14a = require('read14a')
+
+example =[[
+       script run didump
+       script run didump -k aabbccddeeff
+]]
+author = "Iceman"
+usage = "script run didump -k <key> "
+desc = [[
+This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
+
+Arguments:
+       -h             : this help
+       -k <key>       : Mifare Key A.
+]]
+
+local band=bit32.band
+local bor=bit32.bor
+local bnot=bit32.bnot
+local bxor=bit32.bxor
+local lshift=bit32.lshift
+local rshift=bit32.rshift
+
+local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
+local BAR = '286329204469736E65792032303133'
+local RANDOM = FOO..BAR
+local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
+local TIMEOUT = 2000
+local DEBUG = false
+local numBlocks = 20
+local numSectors = 5
+local CHECKSUM_OFFSET = 12; -- +1???
+--- 
+-- A debug printout-function
+function dbg(args)
+       if DEBUG then
+               print("###", args)
+       end
+end 
+--- 
+-- This is only meant to be used when errors occur
+function oops(err)
+       print("ERROR: ",err)
+       core.clearCommandBuffer()
+end
+--- 
+-- Usage help
+function help()
+       print(desc)
+       print("Example usage")
+       print(example)
+end
+---
+-- Get checksum,
+-- called: data is string (32 hex digits)
+-- returns: number
+local function getChecksum(data)
+       local chksum = data:sub(25,32)
+       return tonumber(chksum,16)
+end
+---
+-- calculate checksum
+-- called: data is bytes  (24 hex digits)
+-- returns: number
+local function calculateChecksum(data)
+
+       -- Generate table
+       local _tbl = {}
+_tbl[0] = { 0x0 }
+_tbl[1] = { 0x77073096 }
+_tbl[2] = { 0xEE0E612C }
+_tbl[3] = { 0x990951BA }
+_tbl[4] = { 0x76DC419 }
+_tbl[5] = { 0x706AF48F }
+_tbl[6] = { 0xE963A535 }
+_tbl[7] = { 0x9E6495A3 }
+_tbl[8] = { 0xEDB8832 }
+_tbl[9] = { 0x79DCB8A4 }
+_tbl[10] = { 0xE0D5E91E }
+_tbl[11] = { 0x97D2D988 }
+_tbl[12] = { 0x9B64C2B }
+_tbl[13] = { 0x7EB17CBD }
+_tbl[14] = { 0xE7B82D07 }
+_tbl[15] = { 0x90BF1D91 }
+_tbl[16] = { 0x1DB71064 }
+_tbl[17] = { 0x6AB020F2 }
+_tbl[18] = { 0xF3B97148 }
+_tbl[19] = { 0x84BE41DE }
+_tbl[20] = { 0x1ADAD47D }
+_tbl[21] = { 0x6DDDE4EB }
+_tbl[22] = { 0xF4D4B551 }
+_tbl[23] = { 0x83D385C7 }
+_tbl[24] = { 0x136C9856 }
+_tbl[25] = { 0x646BA8C0 }
+_tbl[26] = { 0xFD62F97A }
+_tbl[27] = { 0x8A65C9EC }
+_tbl[28] = { 0x14015C4F }
+_tbl[29] = { 0x63066CD9 }
+_tbl[30] = { 0xFA0F3D63 }
+_tbl[31] = { 0x8D080DF5 }
+_tbl[32] = { 0x3B6E20C8 }
+_tbl[33] = { 0x4C69105E }
+_tbl[34] = { 0xD56041E4 }
+_tbl[35] = { 0xA2677172 }
+_tbl[36] = { 0x3C03E4D1 }
+_tbl[37] = { 0x4B04D447 }
+_tbl[38] = { 0xD20D85FD }
+_tbl[39] = { 0xA50AB56B }
+_tbl[40] = { 0x35B5A8FA }
+_tbl[41] = { 0x42B2986C }
+_tbl[42] = { 0xDBBBC9D6 }
+_tbl[43] = { 0xACBCF940 }
+_tbl[44] = { 0x32D86CE3 }
+_tbl[45] = { 0x45DF5C75 }
+_tbl[46] = { 0xDCD60DCF }
+_tbl[47] = { 0xABD13D59 }
+_tbl[48] = { 0x26D930AC }
+_tbl[49] = { 0x51DE003A }
+_tbl[50] = { 0xC8D75180 }
+_tbl[51] = { 0xBFD06116 }
+_tbl[52] = { 0x21B4F4B5 }
+_tbl[53] = { 0x56B3C423 }
+_tbl[54] = { 0xCFBA9599 }
+_tbl[55] = { 0xB8BDA50F }
+_tbl[56] = { 0x2802B89E }
+_tbl[57] = { 0x5F058808 }
+_tbl[58] = { 0xC60CD9B2 }
+_tbl[59] = { 0xB10BE924 }
+_tbl[60] = { 0x2F6F7C87 }
+_tbl[61] = { 0x58684C11 }
+_tbl[62] = { 0xC1611DAB }
+_tbl[63] = { 0xB6662D3D }
+_tbl[64] = { 0x76DC4190 }
+_tbl[65] = { 0x1DB7106 }
+_tbl[66] = { 0x98D220BC }
+_tbl[67] = { 0xEFD5102A }
+_tbl[68] = { 0x71B18589 }
+_tbl[69] = { 0x6B6B51F }
+_tbl[70] = { 0x9FBFE4A5 }
+_tbl[71] = { 0xE8B8D433 }
+_tbl[72] = { 0x7807C9A2 }
+_tbl[73] = { 0xF00F934 }
+_tbl[74] = { 0x9609A88E }
+_tbl[75] = { 0xE10E9818 }
+_tbl[76] = { 0x7F6A0DBB }
+_tbl[77] = { 0x86D3D2D }
+_tbl[78] = { 0x91646C97 }
+_tbl[79] = { 0xE6635C01 }
+_tbl[80] = { 0x6B6B51F4 }
+_tbl[81] = { 0x1C6C6162 }
+_tbl[82] = { 0x856530D8 }
+_tbl[83] = { 0xF262004E }
+_tbl[84] = { 0x6C0695ED }
+_tbl[85] = { 0x1B01A57B }
+_tbl[86] = { 0x8208F4C1 }
+_tbl[87] = { 0xF50FC457 }
+_tbl[88] = { 0x65B0D9C6 }
+_tbl[89] = { 0x12B7E950 }
+_tbl[90] = { 0x8BBEB8EA }
+_tbl[91] = { 0xFCB9887C }
+_tbl[92] = { 0x62DD1DDF }
+_tbl[93] = { 0x15DA2D49 }
+_tbl[94] = { 0x8CD37CF3 }
+_tbl[95] = { 0xFBD44C65 }
+_tbl[96] = { 0x4DB26158 }
+_tbl[97] = { 0x3AB551CE }
+_tbl[98] = { 0xA3BC0074 }
+_tbl[99] = { 0xD4BB30E2 }
+_tbl[100] = { 0x4ADFA541 }
+_tbl[101] = { 0x3DD895D7 }
+_tbl[102] = { 0xA4D1C46D }
+_tbl[103] = { 0xD3D6F4FB }
+_tbl[104] = { 0x4369E96A }
+_tbl[105] = { 0x346ED9FC }
+_tbl[106] = { 0xAD678846 }
+_tbl[107] = { 0xDA60B8D0 }
+_tbl[108] = { 0x44042D73 }
+_tbl[109] = { 0x33031DE5 }
+_tbl[110] = { 0xAA0A4C5F }
+_tbl[111] = { 0xDD0D7CC9 }
+_tbl[112] = { 0x5005713C }
+_tbl[113] = { 0x270241AA }
+_tbl[114] = { 0xBE0B1010 }
+_tbl[115] = { 0xC90C2086 }
+_tbl[116] = { 0x5768B525 }
+_tbl[117] = { 0x206F85B3 }
+_tbl[118] = { 0xB966D409 }
+_tbl[119] = { 0xCE61E49F }
+_tbl[120] = { 0x5EDEF90E }
+_tbl[121] = { 0x29D9C998 }
+_tbl[122] = { 0xB0D09822 }
+_tbl[123] = { 0xC7D7A8B4 }
+_tbl[124] = { 0x59B33D17 }
+_tbl[125] = { 0x2EB40D81 }
+_tbl[126] = { 0xB7BD5C3B }
+_tbl[127] = { 0xC0BA6CAD }
+_tbl[128] = { 0xEDB88320 }
+_tbl[129] = { 0x9ABFB3B6 }
+_tbl[130] = { 0x3B6E20C }
+_tbl[131] = { 0x74B1D29A }
+_tbl[132] = { 0xEAD54739 }
+_tbl[133] = { 0x9DD277AF }
+_tbl[134] = { 0x4DB2615 }
+_tbl[135] = { 0x73DC1683 }
+_tbl[136] = { 0xE3630B12 }
+_tbl[137] = { 0x94643B84 }
+_tbl[138] = { 0xD6D6A3E }
+_tbl[139] = { 0x7A6A5AA8 }
+_tbl[140] = { 0xE40ECF0B }
+_tbl[141] = { 0x9309FF9D }
+_tbl[142] = { 0xA00AE27 }
+_tbl[143] = { 0x7D079EB1 }
+_tbl[144] = { 0xF00F9344 }
+_tbl[145] = { 0x8708A3D2 }
+_tbl[146] = { 0x1E01F268 }
+_tbl[147] = { 0x6906C2FE }
+_tbl[148] = { 0xF762575D }
+_tbl[149] = { 0x806567CB }
+_tbl[150] = { 0x196C3671 }
+_tbl[151] = { 0x6E6B06E7 }
+_tbl[152] = { 0xFED41B76 }
+_tbl[153] = { 0x89D32BE0 }
+_tbl[154] = { 0x10DA7A5A }
+_tbl[155] = { 0x67DD4ACC }
+_tbl[156] = { 0xF9B9DF6F }
+_tbl[157] = { 0x8EBEEFF9 }
+_tbl[158] = { 0x17B7BE43 }
+_tbl[159] = { 0x60B08ED5 }
+_tbl[160] = { 0xD6D6A3E8 }
+_tbl[161] = { 0xA1D1937E }
+_tbl[162] = { 0x38D8C2C4 }
+_tbl[163] = { 0x4FDFF252 }
+_tbl[164] = { 0xD1BB67F1 }
+_tbl[165] = { 0xA6BC5767 }
+_tbl[166] = { 0x3FB506DD }
+_tbl[167] = { 0x48B2364B }
+_tbl[168] = { 0xD80D2BDA }
+_tbl[169] = { 0xAF0A1B4C }
+_tbl[170] = { 0x36034AF6 }
+_tbl[171] = { 0x41047A60 }
+_tbl[172] = { 0xDF60EFC3 }
+_tbl[173] = { 0xA867DF55 }
+_tbl[174] = { 0x316E8EEF }
+_tbl[175] = { 0x4669BE79 }
+_tbl[176] = { 0xCB61B38C }
+_tbl[177] = { 0xBC66831A }
+_tbl[178] = { 0x256FD2A0 }
+_tbl[179] = { 0x5268E236 }
+_tbl[180] = { 0xCC0C7795 }
+_tbl[181] = { 0xBB0B4703 }
+_tbl[182] = { 0x220216B9 }
+_tbl[183] = { 0x5505262F }
+_tbl[184] = { 0xC5BA3BBE }
+_tbl[185] = { 0xB2BD0B28 }
+_tbl[186] = { 0x2BB45A92 }
+_tbl[187] = { 0x5CB36A04 }
+_tbl[188] = { 0xC2D7FFA7 }
+_tbl[189] = { 0xB5D0CF31 }
+_tbl[190] = { 0x2CD99E8B }
+_tbl[191] = { 0x5BDEAE1D }
+_tbl[192] = { 0x9B64C2B0 }
+_tbl[193] = { 0xEC63F226 }
+_tbl[194] = { 0x756AA39C }
+_tbl[195] = { 0x26D930A }
+_tbl[196] = { 0x9C0906A9 }
+_tbl[197] = { 0xEB0E363F }
+_tbl[198] = { 0x72076785 }
+_tbl[199] = { 0x5005713 }
+_tbl[200] = { 0x95BF4A82 }
+_tbl[201] = { 0xE2B87A14 }
+_tbl[202] = { 0x7BB12BAE }
+_tbl[203] = { 0xCB61B38 }
+_tbl[204] = { 0x92D28E9B }
+_tbl[205] = { 0xE5D5BE0D }
+_tbl[206] = { 0x7CDCEFB7 }
+_tbl[207] = { 0xBDBDF21 }
+_tbl[208] = { 0x86D3D2D4 }
+_tbl[209] = { 0xF1D4E242 }
+_tbl[210] = { 0x68DDB3F8 }
+_tbl[211] = { 0x1FDA836E }
+_tbl[212] = { 0x81BE16CD }
+_tbl[213] = { 0xF6B9265B }
+_tbl[214] = { 0x6FB077E1 }
+_tbl[215] = { 0x18B74777 }
+_tbl[216] = { 0x88085AE6 }
+_tbl[217] = { 0xFF0F6A70 }
+_tbl[218] = { 0x66063BCA }
+_tbl[219] = { 0x11010B5C }
+_tbl[220] = { 0x8F659EFF }
+_tbl[221] = { 0xF862AE69 }
+_tbl[222] = { 0x616BFFD3 }
+_tbl[223] = { 0x166CCF45 }
+_tbl[224] = { 0xA00AE278 }
+_tbl[225] = { 0xD70DD2EE }
+_tbl[226] = { 0x4E048354 }
+_tbl[227] = { 0x3903B3C2 }
+_tbl[228] = { 0xA7672661 }
+_tbl[229] = { 0xD06016F7 }
+_tbl[230] = { 0x4969474D }
+_tbl[231] = { 0x3E6E77DB }
+_tbl[232] = { 0xAED16A4A }
+_tbl[233] = { 0xD9D65ADC }
+_tbl[234] = { 0x40DF0B66 }
+_tbl[235] = { 0x37D83BF0 }
+_tbl[236] = { 0xA9BCAE53 }
+_tbl[237] = { 0xDEBB9EC5 }
+_tbl[238] = { 0x47B2CF7F }
+_tbl[239] = { 0x30B5FFE9 }
+_tbl[240] = { 0xBDBDF21C }
+_tbl[241] = { 0xCABAC28A }
+_tbl[242] = { 0x53B39330 }
+_tbl[243] = { 0x24B4A3A6 }
+_tbl[244] = { 0xBAD03605 }
+_tbl[245] = { 0xCDD70693 }
+_tbl[246] = { 0x54DE5729 }
+_tbl[247] = { 0x23D967BF }
+_tbl[248] = { 0xB3667A2E }
+_tbl[249] = { 0xC4614AB8 }
+_tbl[250] = { 0x5D681B02 }
+_tbl[251] = { 0x2A6F2B94 }
+_tbl[252] = { 0xB40BBE37 }
+_tbl[253] = { 0xC30C8EA1 }
+_tbl[254] = { 0x5A05DF1B }
+_tbl[255] = { 0x2D02EF8D }
+
+
+       -- Calculate it
+       local ret = 0
+       for i,item in pairs(data) do
+               local tmp =  band(ret, 0xFF)
+               local index = band( bxor(tmp, item), 0xFF)
+               ret = bxor(rshift(ret,8), _tbl[index][1])
+       end
+       return ret
+end
+---
+-- update checksum
+-- called: data is string, ( >= 24 hex digits )
+-- returns: string, (data concat new checksum)
+local function updateChecksum(data)
+       local part = data:sub(1,24)
+       local chksum = calculateChecksum( utils.ConvertHexToBytes(part))        
+       return string.format("%s%X", part, chksum)
+end
+---
+-- receives the answer from deviceside, used with a readblock command
+local function waitCmd()
+       local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
+       if response then
+               local count,cmd,arg0 = bin.unpack('LL',response)
+               if(arg0==1) then
+                       local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
+                       return data:sub(1,32)
+               else
+                       return nil, "Couldn't read block.." 
+               end
+       end
+       return nil, "No response from device"
+end
+
+local function selftest()
+       local testdata = '000F42430D0A14000001D11F'..'5D738517'
+       local chksum = getChecksum(testdata)
+       local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))    
+       print  ('TESTDATA    :: '..testdata)
+       print  ('DATA        :: '..testdata:sub(1,24))
+       print (('CHKSUM      :: %X'):format(chksum))    
+       print (('CHKSUM CALC :: %X'):format(calc))      
+       print ('UPDATE CHKSUM :: '..updateChecksum(testdata))
+       
+       
+end
+--- 
+-- The main entry point
+-- -d decrypt
+-- -e encrypt
+-- -v validate
+function main(args)
+
+       local cmd, result, err, blockNo, keyA
+       local blocks = {}
+       local decryptkey = ''
+       
+       -- Read the parameters
+       for o, a in getopt.getopt(args, 'hk:') do
+               if o == "h" then help() return end
+               if o == "k" then keyA = a end
+       end
+       
+       selftest()
+       
+       local tst2 = '00100100030209094312356432324E34B79A349B'
+       
+       -- validate input args.
+       keyA =  keyA or '6dd747e86975'
+       if #(keyA) ~= 12 then
+               return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
+       end
+       
+       -- Turn off Debug
+       local cmdSetDbgOff = "hf mf dbg 0"
+       core.console( cmdSetDbgOff) 
+
+       -- GET TAG UID
+       
+       result, err = lib14a.read1443a(false)
+       if not result then
+               return oops(err)
+       end
+
+       core.clearCommandBuffer()
+
+       print(result.uid, keyA)
+
+       local my = result.uid
+       if 1 == 1 then 
+               return
+       end
+       
+       -- Show tag info
+       print((' Found tag %s'):format(result.name))
+       
+       local longrandom = RANDOM..result.uid
+       local res = utils.Sha1Hex(longrandom)
+       res  = utils.ConvertBytesToHex(utils.ConvertAsciiToBytes(res:sub(1,16)))
+       decryptkey = utils.SwapEndiannessStr(res:sub(1,8) , 32)
+       decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(9,16),32)
+       decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(17,24),32)
+       decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(25,32),32)
+       print('Decrypt key::',decryptkey)
+       print('Reading card data')
+       print('Raw','Decrypted')
+       for blockNo = 0, numBlocks-1, 1 do
+
+               if core.ukbhit() then
+                       print("aborted by user")
+                       break
+               end
+
+               cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = keyA}
+               local err = core.SendCommand(cmd:getBytes())
+               if err then return oops(err) end
+               local blockdata, err = waitCmd()
+               if err then return oops(err) end        
+                       
+               if  blockNo%4 ~= 3 then
+                       
+                       -- blocks with zero not encrypted.
+                       if string.find(blockdata, '^0+$') then
+                               print(blockdata, blockdata)
+                       else
+                               local aes = core.aes128_decrypt_ecb(decryptkey, blockdata)
+                               local bytes =  utils.ConvertAsciiToBytes(aes)
+                               local hex = utils.ConvertBytesToHex(bytes)
+                               print(blockdata , hex)
+                       end
+               elseif blockNo == 0 then
+                       print(blockdata,blockdata)
+               else
+                       -- Sectorblocks, not encrypted
+                       local sectortrailer = keyA..blockdata:sub(13,20)..keyA
+                       print(sectortrailer, sectortrailer, blockdata:sub(13,20))
+               end
+       end
+       -- checksum fyra sista bytes i varje rad.  (kanske inte för s0)
+       -- s0b1,s1b0,s2b0,s3b0
+       -- 
+end
+
+main(args)
index f9b715091c7e2ebe92b2532d02f4249c13538501..f8cc11d455da2fa0bbea72fab9bb0c389b680d0d 100644 (file)
@@ -73,7 +73,8 @@ local function convert_to_emulform(hexdata)
        for i = 1, string.len(hexdata),32 do
                ascii = ascii  ..string.sub(hexdata,i,i+31).."\n"
        end
-       return ascii
+       
+       return string.sub(ascii,1,-1)
 end
 
 local function main(args)
index cea9f7d734a81150d1f5536118364552dcbfa807..9f2142c6a4114d7c2e6f50f6ac97fca70c709522 100644 (file)
@@ -108,12 +108,12 @@ void print_hex(const uint8_t * data, const size_t len)
        printf("\n");
 }
 
-char * sprint_hex(const uint8_t * data, const size_t len) {
+char *sprint_hex(const uint8_t *data, const size_t len) {
        
        int maxLen = ( len > 1024/3) ? 1024/3 : len;
        static char buf[1024];
        memset(buf, 0x00, 1024);
-       char * tmp = buf;
+       char *tmp = buf;
        size_t i;
 
        for (i=0; i < maxLen; ++i, tmp += 3)
@@ -394,7 +394,7 @@ int hextobinstring(char *target, char *source)
 
 // convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
 // return number of bits converted
-int binarraytohex(char *target, char *source, int length)
+int binarraytohex(char *target,char *source, int length)
 {
     unsigned char i, x;
     int j = length;
@@ -444,3 +444,12 @@ void wiegand_add_parity(char *target, char *source, char length)
     target += length;
     *(target)= GetParity(source + length / 2, ODD, length / 2);
 }
+
+void xor(unsigned char *dst, unsigned char *src, size_t len) {
+   for( ; len > 0; len--,dst++,src++)
+       *dst ^= *src;
+}
+
+int32_t le24toh (uint8_t data[3]) {
+    return (data[2] << 16) | (data[1] << 8) | data[0];
+}
index f58f64cb47200defd20fb82aa084bebd5dccf18e..2d2beaf42cd12169babe5b12c603ef7680a4c3b4 100644 (file)
@@ -63,3 +63,5 @@ void binarraytobinstring(char *target,  char *source,  int length);
 uint8_t GetParity( char *string, uint8_t type,  int length);
 void wiegand_add_parity(char *target, char *source, char length);
 
+void xor(unsigned char *dst, unsigned char *src, size_t len);
+int32_t le24toh(uint8_t data[3]);
index 973cd103c009b16697b7523b1cbf60b107500f7a..a37f1d7e35f69e63e6fba2259f0a011b8f1bf4ec 100644 (file)
@@ -8,38 +8,54 @@
 
 #include "crc16.h"
 
-
 unsigned short update_crc16( unsigned short crc, unsigned char c )
 {
-  unsigned short i, v, tcrc = 0;
+       unsigned short i, v, tcrc = 0;
 
-  v = (crc ^ c) & 0xff;
-  for (i = 0; i < 8; i++) {
-      tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1;
-      v >>= 1;
-  }
+       v = (crc ^ c) & 0xff;
+       for (i = 0; i < 8; i++) {
+               tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1;
+               v >>= 1;
+       }
 
-  return ((crc >> 8) ^ tcrc)&0xffff;
+       return ((crc >> 8) ^ tcrc)&0xffff;
 }
 
 uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial) {
-    
-       if (length == 0)
-        return (~remainder);
-                       
-    for (int byte = 0; byte < length; ++byte) {
-        remainder ^= (message[byte] << 8);
-        for (uint8_t bit = 8; bit > 0; --bit) {
-            if (remainder & 0x8000) {
-                remainder = (remainder << 1) ^ polynomial;
-            } else {
-                remainder = (remainder << 1);
-            }
-        }
-    }
-    return remainder;
+
+       if (length == 0) return (~remainder);
+
+       for (int byte = 0; byte < length; ++byte) {
+               remainder ^= (message[byte] << 8);
+               for (uint8_t bit = 8; bit > 0; --bit) {
+                       if (remainder & 0x8000) {
+                               remainder = (remainder << 1) ^ polynomial;
+                       } else {
+                               remainder = (remainder << 1);
+                       }
+               }
+       }
+       return remainder;
 }
 
 uint16_t crc16_ccitt(uint8_t const *message, int length) {
-    return crc16(message, length, 0xffff, 0x1021);
+       return crc16(message, length, 0xffff, 0x1021);
+}
+
+uint16_t crc16_ccitt_kermit(uint8_t const *message, int length) {
+       return bit_reverse_uint16(crc16(message, length, 0x0000, 0x1021));
+}
+
+uint16_t bit_reverse_uint16 (uint16_t value) {
+       const uint16_t mask0 = 0x5555;
+       const uint16_t mask1 = 0x3333;
+       const uint16_t mask2 = 0x0F0F;
+       const uint16_t mask3 = 0x00FF;
+
+       value = (((~mask0) & value) >> 1) | ((mask0 & value) << 1);
+       value = (((~mask1) & value) >> 2) | ((mask1 & value) << 2);
+       value = (((~mask2) & value) >> 4) | ((mask2 & value) << 4);
+       value = (((~mask3) & value) >> 8) | ((mask3 & value) << 8);
+
+       return value;
 }
index d16d83b5afdb162c088e35e4a01aee33e2760e3d..8eb4befbcf1d7566cf0d7f8f73c370f29080e0ba 100644 (file)
@@ -12,4 +12,6 @@
 unsigned short update_crc16(unsigned short crc, unsigned char c);
 uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial);
 uint16_t crc16_ccitt(uint8_t const *message, int length);
+uint16_t crc16_ccitt_kermit(uint8_t const *message, int length);
+uint16_t bit_reverse_uint16 (uint16_t value);
 #endif
index 7d40d22e5aa44551835ae4ada1f69947f132e488..f13a567c6fe8cda87b1cf70248cd201603fe023f 100644 (file)
@@ -526,7 +526,7 @@ int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, ui
        return (int)startIdx;
 }
 
-uint32_t bytebits_to_byte(uint8_tsrc, size_t numbits)
+uint32_t bytebits_to_byte(uint8_t *src, size_t numbits)
 {
        uint32_t num = 0;
        for(int i = 0 ; i < numbits ; i++)
@@ -537,6 +537,17 @@ uint32_t bytebits_to_byte(uint8_t* src, size_t numbits)
        return num;
 }
 
+//least significant bit first
+uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
+{
+       uint32_t num = 0;
+       for(int i = 0 ; i < numbits ; i++)
+       {
+               num = (num << 1) | *(src + (numbits-(i+1)));
+       }
+       return num;
+}
+
 int IOdemodFSK(uint8_t *dest, size_t size)
 {
        if (justNoise(dest, size)) return -1;
@@ -569,7 +580,7 @@ int IOdemodFSK(uint8_t *dest, size_t size)
 
 // by marshmellow
 // takes a array of binary values, start position, length of bits per parity (includes parity bit),
-//   Parity Type (1 for odd 0 for even), and binary Length (length to run) 
+//   Parity Type (1 for odd; 0 for even; 2 for just drop it), and binary Length (length to run) 
 size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
 {
        uint32_t parityWd = 0;
@@ -581,7 +592,9 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
                }
                j--;
                // if parity fails then return 0
-               if (parityTest(parityWd, pLen, pType) == 0) return -1;
+               if (pType != 2) {
+                       if (parityTest(parityWd, pLen, pType) == 0) return -1;
+               }
                bitCnt+=(pLen-1);
                parityWd = 0;
        }
@@ -590,6 +603,21 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
        return bitCnt;
 }
 
+// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
+// BitStream must contain previously askrawdemod and biphasedemoded data
+int FDXBdemodBI(uint8_t *dest, size_t *size)
+{
+       //make sure buffer has enough data
+       if (*size < 128) return -1;
+
+       size_t startIdx = 0;
+       uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,0,1};
+
+       uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+       if (errChk == 0) return -2; //preamble not found
+       return (int)startIdx;
+}
+
 // by marshmellow
 // FSK Demod then try to locate an AWID ID
 int AWIDdemodFSK(uint8_t *dest, size_t *size)
index ab81c34c459ef327cbe3ea595af3f1ecf1d5a72b..d16aab9eb4205ff1f34a1438411ad04bc1f0820e 100644 (file)
@@ -19,6 +19,7 @@
 int      askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType);
 int      BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
 uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
+uint32_t bytebits_to_byteLSBF(uint8_t* src, size_t numbits);
 uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
 int      DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr);
 uint8_t  DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
@@ -40,6 +41,7 @@ void     psk1TOpsk2(uint8_t *BitStream, size_t size);
 size_t   removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
 
 //tag specific
+int FDXBdemodBI(uint8_t *dest, size_t *size);
 int AWIDdemodFSK(uint8_t *dest, size_t *size);
 int gProxII_Demod(uint8_t BitStream[], size_t *size);
 int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
index 6a4c9a103bff1a03ebb21215e968b54bc9aa7f09..aa80491b58f2b94d61313e01e1b4b4a2f64ac6a5 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdio.h>
 #include <strings.h>
 #include <string.h>
 #include <stdint.h>
diff --git a/common/sha1.c b/common/sha1.c
new file mode 100644 (file)
index 0000000..d20c54a
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ *  FIPS-180-1 compliant SHA-1 implementation
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *  This file is part of mbed TLS (https://tls.mbed.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, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-1 standard was published by NIST in 1993.
+ *
+ *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+//#include "polarssl/config.h"
+#define POLARSSL_SHA1_C
+
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+
+#include "sha1.h"
+
+#include <string.h>
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif /* POLARSSL_PLATFORM_C */
+#endif /* POLARSSL_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#if !defined(POLARSSL_SHA1_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+void sha1_init( sha1_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha1_context ) );
+}
+
+void sha1_free( sha1_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha1_context ) );
+}
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts( sha1_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+}
+
+void sha1_process( sha1_context *ctx, const unsigned char data[64] )
+{
+    uint32_t temp, W[16], A, B, C, D, E;
+
+    GET_UINT32_BE( W[ 0], data,  0 );
+    GET_UINT32_BE( W[ 1], data,  4 );
+    GET_UINT32_BE( W[ 2], data,  8 );
+    GET_UINT32_BE( W[ 3], data, 12 );
+    GET_UINT32_BE( W[ 4], data, 16 );
+    GET_UINT32_BE( W[ 5], data, 20 );
+    GET_UINT32_BE( W[ 6], data, 24 );
+    GET_UINT32_BE( W[ 7], data, 28 );
+    GET_UINT32_BE( W[ 8], data, 32 );
+    GET_UINT32_BE( W[ 9], data, 36 );
+    GET_UINT32_BE( W[10], data, 40 );
+    GET_UINT32_BE( W[11], data, 44 );
+    GET_UINT32_BE( W[12], data, 48 );
+    GET_UINT32_BE( W[13], data, 52 );
+    GET_UINT32_BE( W[14], data, 56 );
+    GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t)                                            \
+(                                                       \
+    temp = W[( t -  3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
+           W[( t - 14 ) & 0x0F] ^ W[  t       & 0x0F],  \
+    ( W[t & 0x0F] = S(temp,1) )                         \
+)
+
+#define P(a,b,c,d,e,x)                                  \
+{                                                       \
+    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+    P( A, B, C, D, E, W[0]  );
+    P( E, A, B, C, D, W[1]  );
+    P( D, E, A, B, C, W[2]  );
+    P( C, D, E, A, B, W[3]  );
+    P( B, C, D, E, A, W[4]  );
+    P( A, B, C, D, E, W[5]  );
+    P( E, A, B, C, D, W[6]  );
+    P( D, E, A, B, C, W[7]  );
+    P( C, D, E, A, B, W[8]  );
+    P( B, C, D, E, A, W[9]  );
+    P( A, B, C, D, E, W[10] );
+    P( E, A, B, C, D, W[11] );
+    P( D, E, A, B, C, W[12] );
+    P( C, D, E, A, B, W[13] );
+    P( B, C, D, E, A, W[14] );
+    P( A, B, C, D, E, W[15] );
+    P( E, A, B, C, D, R(16) );
+    P( D, E, A, B, C, R(17) );
+    P( C, D, E, A, B, R(18) );
+    P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+    P( A, B, C, D, E, R(20) );
+    P( E, A, B, C, D, R(21) );
+    P( D, E, A, B, C, R(22) );
+    P( C, D, E, A, B, R(23) );
+    P( B, C, D, E, A, R(24) );
+    P( A, B, C, D, E, R(25) );
+    P( E, A, B, C, D, R(26) );
+    P( D, E, A, B, C, R(27) );
+    P( C, D, E, A, B, R(28) );
+    P( B, C, D, E, A, R(29) );
+    P( A, B, C, D, E, R(30) );
+    P( E, A, B, C, D, R(31) );
+    P( D, E, A, B, C, R(32) );
+    P( C, D, E, A, B, R(33) );
+    P( B, C, D, E, A, R(34) );
+    P( A, B, C, D, E, R(35) );
+    P( E, A, B, C, D, R(36) );
+    P( D, E, A, B, C, R(37) );
+    P( C, D, E, A, B, R(38) );
+    P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+    P( A, B, C, D, E, R(40) );
+    P( E, A, B, C, D, R(41) );
+    P( D, E, A, B, C, R(42) );
+    P( C, D, E, A, B, R(43) );
+    P( B, C, D, E, A, R(44) );
+    P( A, B, C, D, E, R(45) );
+    P( E, A, B, C, D, R(46) );
+    P( D, E, A, B, C, R(47) );
+    P( C, D, E, A, B, R(48) );
+    P( B, C, D, E, A, R(49) );
+    P( A, B, C, D, E, R(50) );
+    P( E, A, B, C, D, R(51) );
+    P( D, E, A, B, C, R(52) );
+    P( C, D, E, A, B, R(53) );
+    P( B, C, D, E, A, R(54) );
+    P( A, B, C, D, E, R(55) );
+    P( E, A, B, C, D, R(56) );
+    P( D, E, A, B, C, R(57) );
+    P( C, D, E, A, B, R(58) );
+    P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+    P( A, B, C, D, E, R(60) );
+    P( E, A, B, C, D, R(61) );
+    P( D, E, A, B, C, R(62) );
+    P( C, D, E, A, B, R(63) );
+    P( B, C, D, E, A, R(64) );
+    P( A, B, C, D, E, R(65) );
+    P( E, A, B, C, D, R(66) );
+    P( D, E, A, B, C, R(67) );
+    P( C, D, E, A, B, R(68) );
+    P( B, C, D, E, A, R(69) );
+    P( A, B, C, D, E, R(70) );
+    P( E, A, B, C, D, R(71) );
+    P( D, E, A, B, C, R(72) );
+    P( C, D, E, A, B, R(73) );
+    P( B, C, D, E, A, R(74) );
+    P( A, B, C, D, E, R(75) );
+    P( E, A, B, C, D, R(76) );
+    P( D, E, A, B, C, R(77) );
+    P( C, D, E, A, B, R(78) );
+    P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen == 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        sha1_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        sha1_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_BE( high, msglen, 0 );
+    PUT_UINT32_BE( low,  msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    sha1_update( ctx, sha1_padding, padn );
+    sha1_update( ctx, msglen, 8 );
+
+    PUT_UINT32_BE( ctx->state[0], output,  0 );
+    PUT_UINT32_BE( ctx->state[1], output,  4 );
+    PUT_UINT32_BE( ctx->state[2], output,  8 );
+    PUT_UINT32_BE( ctx->state[3], output, 12 );
+    PUT_UINT32_BE( ctx->state[4], output, 16 );
+}
+
+#endif /* !POLARSSL_SHA1_ALT */
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
+{
+    sha1_context ctx;
+
+    sha1_init( &ctx );
+    sha1_starts( &ctx );
+    sha1_update( &ctx, input, ilen );
+    sha1_finish( &ctx, output );
+    sha1_free( &ctx );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-1( file contents )
+ */
+int sha1_file( const char *path, unsigned char output[20] )
+{
+    FILE *f;
+    size_t n;
+    sha1_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+
+    sha1_init( &ctx );
+    sha1_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha1_update( &ctx, buf, n );
+
+    sha1_finish( &ctx, output );
+    sha1_free( &ctx );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-1 HMAC context setup
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
+                       size_t keylen )
+{
+    size_t i;
+    unsigned char sum[20];
+
+    if( keylen > 64 )
+    {
+        sha1( key, keylen, sum );
+        keylen = 20;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->ipad, 64 );
+
+    polarssl_zeroize( sum, sizeof( sum ) );
+}
+
+/*
+ * SHA-1 HMAC process buffer
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
+                       size_t ilen )
+{
+    sha1_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-1 HMAC final digest
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
+{
+    unsigned char tmpbuf[20];
+
+    sha1_finish( ctx, tmpbuf );
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->opad, 64 );
+    sha1_update( ctx, tmpbuf, 20 );
+    sha1_finish( ctx, output );
+
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA1 HMAC context reset
+ */
+void sha1_hmac_reset( sha1_context *ctx )
+{
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-1( hmac key, input buffer )
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[20] )
+{
+    sha1_context ctx;
+
+    sha1_init( &ctx );
+    sha1_hmac_starts( &ctx, key, keylen );
+    sha1_hmac_update( &ctx, input, ilen );
+    sha1_hmac_finish( &ctx, output );
+    sha1_free( &ctx );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static const unsigned char sha1_test_buf[3][57] =
+{
+    { "abc" },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+    { "" }
+};
+
+static const int sha1_test_buflen[3] =
+{
+    3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static const unsigned char sha1_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 80 times */
+    { "" }
+};
+
+static const int sha1_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 80, 80
+};
+
+static const unsigned char sha1_hmac_test_buf[7][74] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "Test Using Larger Than Block-Size Key and Larger"
+      " Than One Block-Size Data" }
+};
+
+static const int sha1_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char sha1_hmac_test_sum[7][20] =
+{
+    { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
+      0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
+    { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
+      0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
+    { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
+      0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
+    { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
+      0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
+    { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
+      0x7B, 0xE1 },
+    { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
+      0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
+    { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
+      0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( int verbose )
+{
+    int i, j, buflen, ret = 0;
+    unsigned char buf[1024];
+    unsigned char sha1sum[20];
+    sha1_context ctx;
+
+    sha1_init( &ctx );
+
+    /*
+     * SHA-1
+     */
+    for( i = 0; i < 3; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  SHA-1 test #%d: ", i + 1 );
+
+        sha1_starts( &ctx );
+
+        if( i == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha1_update( &ctx, buf, buflen );
+        }
+        else
+            sha1_update( &ctx, sha1_test_buf[i],
+                               sha1_test_buflen[i] );
+
+        sha1_finish( &ctx, sha1sum );
+
+        if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
+
+        if( i == 5 || i == 6 )
+        {
+            memset( buf, 0xAA, buflen = 80 );
+            sha1_hmac_starts( &ctx, buf, buflen );
+        }
+        else
+            sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
+                                    sha1_hmac_test_keylen[i] );
+
+        sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
+                                sha1_hmac_test_buflen[i] );
+
+        sha1_hmac_finish( &ctx, sha1sum );
+
+        buflen = ( i == 4 ) ? 12 : 20;
+
+        if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+exit:
+    sha1_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_SHA1_C */
+
diff --git a/common/sha1.h b/common/sha1.h
new file mode 100644 (file)
index 0000000..056bba7
--- /dev/null
@@ -0,0 +1,213 @@
+/**
+ * \file sha1.h
+ *
+ * \brief SHA-1 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.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, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA1_H
+#define POLARSSL_SHA1_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+//#include "config.h"
+/**
+ * \def POLARSSL_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module:  library/sha1.c
+ * Caller:  library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509write_crt.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_SHA1_FILE_IO_ERROR                -0x0076  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_SHA1_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-1 context structure
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< number of bytes processed  */
+    uint32_t state[5];          /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+sha1_context;
+
+/**
+ * \brief          Initialize SHA-1 context
+ *
+ * \param ctx      SHA-1 context to be initialized
+ */
+void sha1_init( sha1_context *ctx );
+
+/**
+ * \brief          Clear SHA-1 context
+ *
+ * \param ctx      SHA-1 context to be cleared
+ */
+void sha1_free( sha1_context *ctx );
+
+/**
+ * \brief          SHA-1 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void sha1_starts( sha1_context *ctx );
+
+/**
+ * \brief          SHA-1 process buffer
+ *
+ * \param ctx      SHA-1 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-1 final digest
+ *
+ * \param ctx      SHA-1 context
+ * \param output   SHA-1 checksum result
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] );
+
+/* Internal use */
+void sha1_process( sha1_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_SHA1_ALT */
+#include "sha1_alt.h"
+#endif /* POLARSSL_SHA1_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = SHA-1( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-1 checksum result
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
+
+/**
+ * \brief          Output = SHA-1( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-1 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
+ */
+int sha1_file( const char *path, unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
+                       size_t keylen );
+
+/**
+ * \brief          SHA-1 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
+                       size_t ilen );
+
+/**
+ * \brief          SHA-1 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-1 HMAC checksum result
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha1_hmac_reset( sha1_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-1( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-1 result
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[20] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */
index 20fb2bd4401254d899d6273451bfccbd827f562b..50c7eef97c8b98461b7d8be9e4e643dd85910241 100644 (file)
Binary files a/fpga/fpga_hf.bit and b/fpga/fpga_hf.bit differ
index a2100df65f5212761b03b1f4ba1e7a53d8d67ca0..8a465e75c5304452b598d5d28d5f2f4ae16f8c6f 100644 (file)
@@ -73,9 +73,6 @@ wire hi_read_rx_xcorr_848 = conf_word[0];
 // and whether to drive the coil (reader) or just short it (snooper)
 wire hi_read_rx_xcorr_snoop = conf_word[1];
 
-// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4
-wire hi_read_rx_xcorr_quarter = conf_word[2];
-
 // For the high-frequency simulated tag: what kind of modulation to use.
 wire [2:0] hi_simulate_mod_type = conf_word[2:0];
 
@@ -102,7 +99,7 @@ hi_read_rx_xcorr hrxc(
        hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
        cross_hi, cross_lo,
        hrxc_dbg,
-       hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
+       hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop
 );
 
 hi_simulate hs(
index dece2db3195844ce9ce2d371d09a1ff7df0069bf..afaf7cb6fb17ae0a1f5687a9b48601ead3d65c23 100644 (file)
@@ -10,7 +10,7 @@ module hi_read_rx_xcorr(
     ssp_frame, ssp_din, ssp_dout, ssp_clk,
     cross_hi, cross_lo,
     dbg,
-    xcorr_is_848, snoop, xcorr_quarter_freq
+    xcorr_is_848, snoop
 );
     input pck0, ck_1356meg, ck_1356megb;
     output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@@ -20,58 +20,24 @@ module hi_read_rx_xcorr(
     output ssp_frame, ssp_din, ssp_clk;
     input cross_hi, cross_lo;
     output dbg;
-    input xcorr_is_848, snoop, xcorr_quarter_freq;
+    input xcorr_is_848, snoop;
 
 // Carrier is steady on through this, unless we're snooping.
 assign pwr_hi = ck_1356megb & (~snoop);
 assign pwr_oe1 = 1'b0;
-assign pwr_oe2 = 1'b0;
 assign pwr_oe3 = 1'b0;
 assign pwr_oe4 = 1'b0;
 
-reg ssp_clk;
-reg ssp_frame;
+wire adc_clk = ck_1356megb;
 
 reg fc_div_2;
-always @(posedge ck_1356meg)
-    fc_div_2 = ~fc_div_2;
-
-reg fc_div_4;
-always @(posedge fc_div_2)
-    fc_div_4 = ~fc_div_4;
-
-reg fc_div_8;
-always @(posedge fc_div_4)
-    fc_div_8 = ~fc_div_8;
-
-reg adc_clk;
-
-always @(xcorr_is_848 or xcorr_quarter_freq or ck_1356meg)
-    if(~xcorr_quarter_freq)
-    begin
-           if(xcorr_is_848)
-               // The subcarrier frequency is fc/16; we will sample at fc, so that 
-               // means the subcarrier is 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 ...
-               adc_clk <= ck_1356meg;
-           else
-               // The subcarrier frequency is fc/32; we will sample at fc/2, and
-               // the subcarrier will look identical.
-               adc_clk <= fc_div_2;
-    end
-    else
-    begin
-           if(xcorr_is_848)
-               // The subcarrier frequency is fc/64
-               adc_clk <= fc_div_4;
-           else
-               // The subcarrier frequency is fc/128
-               adc_clk <= fc_div_8;
-       end
+always @(negedge ck_1356megb)
+    fc_div_2 <= fc_div_2 + 1;
 
 // When we're a reader, we just need to do the BPSK demod; but when we're an
 // eavesdropper, we also need to pick out the commands sent by the reader,
 // using AM. Do this the same way that we do it for the simulated tag.
-reg after_hysteresis, after_hysteresis_prev;
+reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev;
 reg [11:0] has_been_low_for;
 always @(negedge adc_clk)
 begin
@@ -97,12 +63,24 @@ end
 // Let us report a correlation every 4 subcarrier cycles, or 4*16 samples,
 // so we need a 6-bit counter.
 reg [5:0] corr_i_cnt;
-reg [5:0] corr_q_cnt;
 // And a couple of registers in which to accumulate the correlations.
-reg signed [15:0] corr_i_accum;
-reg signed [15:0] corr_q_accum;
+// we would add at most 32 times adc_d, the result can be held in 13 bits. 
+// Need one additional bit because it can be negative as well
+reg signed [13:0] corr_i_accum;
+reg signed [13:0] corr_q_accum;
 reg signed [7:0] corr_i_out;
 reg signed [7:0] corr_q_out;
+// clock and frame signal for communication to ARM
+reg ssp_clk;
+reg ssp_frame;
+
+
+always @(negedge adc_clk)
+begin
+       if (xcorr_is_848 | fc_div_2)
+               corr_i_cnt <= corr_i_cnt + 1;
+end            
+               
 
 // ADC data appears on the rising edge, so sample it on the falling edge
 always @(negedge adc_clk)
@@ -110,24 +88,24 @@ begin
     // These are the correlators: we correlate against in-phase and quadrature
     // versions of our reference signal, and keep the (signed) result to
     // send out later over the SSP.
-    if(corr_i_cnt == 7'd63)
+    if(corr_i_cnt == 6'd0)
     begin
         if(snoop)
         begin
-            corr_i_out <= {corr_i_accum[12:6], after_hysteresis_prev};
-            corr_q_out <= {corr_q_accum[12:6], after_hysteresis};
+                       // Send only 7 most significant bits of tag signal (signed), LSB is reader signal:
+            corr_i_out <= {corr_i_accum[13:7], after_hysteresis_prev_prev};
+            corr_q_out <= {corr_q_accum[13:7], after_hysteresis_prev};
+                       after_hysteresis_prev_prev <= after_hysteresis;
         end
         else
         begin
-            // Only correlations need to be delivered.
+            // 8 most significant bits of tag signal
             corr_i_out <= corr_i_accum[13:6];
             corr_q_out <= corr_q_accum[13:6];
         end
 
         corr_i_accum <= adc_d;
         corr_q_accum <= adc_d;
-        corr_q_cnt <= 4;
-        corr_i_cnt <= 0;
     end
     else
     begin
@@ -136,18 +114,16 @@ begin
         else
             corr_i_accum <= corr_i_accum + adc_d;
 
-        if(corr_q_cnt[3])
-            corr_q_accum <= corr_q_accum - adc_d;
-        else
+        if(corr_i_cnt[3] == corr_i_cnt[2])                     // phase shifted by pi/2
             corr_q_accum <= corr_q_accum + adc_d;
+        else
+            corr_q_accum <= corr_q_accum - adc_d;
 
-        corr_i_cnt <= corr_i_cnt + 1;
-        corr_q_cnt <= corr_q_cnt + 1;
     end
 
     // The logic in hi_simulate.v reports 4 samples per bit. We report two
     // (I, Q) pairs per bit, so we should do 2 samples per pair.
-    if(corr_i_cnt == 6'd31)
+    if(corr_i_cnt == 6'd32)
         after_hysteresis_prev <= after_hysteresis;
 
     // Then the result from last time is serialized and send out to the ARM.
@@ -168,7 +144,9 @@ begin
         end
     end
 
-    if(corr_i_cnt[5:2] == 4'b000 || corr_i_cnt[5:2] == 4'b1000)
+       // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35
+       // (send two frames with 8 Bits each)
+    if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000)
         ssp_frame = 1'b1;
     else
         ssp_frame = 1'b0;
@@ -181,5 +159,6 @@ assign dbg = corr_i_cnt[3];
 
 // Unused.
 assign pwr_lo = 1'b0;
+assign pwr_oe2 = 1'b0;
 
 endmodule
index 357395d43f3103eb01a66144648dbd2e97d001e9..524554e9384b1db9c715a182df6bddf08431c3b2 100644 (file)
@@ -100,7 +100,6 @@ typedef struct{
 
 // For the 13.56 MHz tags
 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693                             0x0300
-#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443                             0x0301
 #define CMD_READ_SRI512_TAG                                               0x0303
 #define CMD_READ_SRIX4K_TAG                                               0x0304
 #define CMD_ISO_14443B_COMMAND                                            0x0305
@@ -118,9 +117,8 @@ typedef struct{
 #define CMD_SIMULATE_HITAG                                                0x0371
 #define CMD_READER_HITAG                                                  0x0372
 
-#define CMD_SIMULATE_TAG_HF_LISTEN                                        0x0380
-#define CMD_SIMULATE_TAG_ISO_14443                                        0x0381
-#define CMD_SNOOP_ISO_14443                                               0x0382
+#define CMD_SIMULATE_TAG_ISO_14443B                                       0x0381
+#define CMD_SNOOP_ISO_14443B                                              0x0382
 #define CMD_SNOOP_ISO_14443a                                              0x0383
 #define CMD_SIMULATE_TAG_ISO_14443a                                       0x0384
 #define CMD_READER_ISO_14443a                                             0x0385
@@ -128,6 +126,7 @@ typedef struct{
 #define CMD_READER_LEGIC_RF                                               0x0388
 #define CMD_WRITER_LEGIC_RF                                               0x0389
 #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
+#define CMD_EPA_PACE_REPLAY                                               0x038B
 
 #define CMD_SNOOP_ICLASS                                                  0x0392
 #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
Impressum, Datenschutz