From 0de8e3874d6524379550a50a4d9c29faf2d239ea Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Oct 2015 18:01:33 +0200 Subject: [PATCH] A lot of changes... .. ntag simulation stuff from @marshmellows branch "ntag/sim" .. hf mf mifare fixes from @pwpivi. .. hw status command .. speedtest function from @pwpivi .. Viking Functionalities, (not a proper DEMOD, but a start) .. GetCountUS better precision from @pwpivi .. bin2hex, hex2bin from @holiman ... starting with getting the T55x7 CONFIGURATION_BLOCK for different clone situations. Ripped from Adam Lauries RFidler, nothing working or finished.. ... Started working with the T55x7 read command with password actually performs a write block... See Issue #136 https://github.com/Proxmark/proxmark3/issues/136 Not solved yet. ... Started add SHA256.. not working yet.. --- CHANGELOG.md | 1 + armsrc/appmain.c | 39 +- armsrc/apps.h | 1 + armsrc/iso14443a.c | 102 +++-- armsrc/lfops.c | 89 +++-- armsrc/mifarecmd.c | 3 +- armsrc/mifareutil.c | 8 +- armsrc/mifareutil.h | 1 + armsrc/util.c | 4 +- bootrom/Makefile | 4 +- client/Makefile | 2 + client/cmddata.c | 150 ++++++- client/cmddata.h | 3 +- client/cmdhf.c | 2 +- client/cmdhfmf.c | 20 +- client/cmdhfmfu.c | 23 +- client/cmdhw.c | 48 ++- client/cmdlf.c | 69 +++- client/cmdlft55xx.c | 1 + client/cmdlft55xx.h | 20 + client/cmdlfviking.c | 65 +++ client/cmdlfviking.h | 7 + client/cmdmain.c | 13 +- client/hid-flasher/usb_cmd.h | 1 + client/lualibs/commands.lua | 5 +- client/mifarehost.c | 42 +- client/mifarehost.h | 1 + client/nonce2key/nonce2key.c | 115 +++--- client/scripts/dumptoemul-mfu.lua | 122 ++++++ client/scripts/mifare_autopwn.lua | 2 + client/util.h | 1 + common/cmd.c | 46 ++- common/hmac_drbg.c | 533 +++++++++++++++++++++++++ common/hmac_drbg.h | 300 ++++++++++++++ common/lfdemod.c | 27 ++ common/lfdemod.h | 1 + common/sha256.c | 446 +++++++++++++++++++++ common/sha256.h | 142 +++++++ doc/RFID_Antenna-Basic-Form.stl | Bin 0 -> 3084 bytes doc/RFID_Antenna-With-Lanyard-Hook.stl | Bin 0 -> 8484 bytes include/usb_cmd.h | 2 + 41 files changed, 2223 insertions(+), 238 deletions(-) create mode 100644 client/cmdlfviking.c create mode 100644 client/cmdlfviking.h create mode 100644 client/scripts/dumptoemul-mfu.lua create mode 100644 common/hmac_drbg.c create mode 100644 common/hmac_drbg.h create mode 100644 common/sha256.c create mode 100644 common/sha256.h create mode 100644 doc/RFID_Antenna-Basic-Form.stl create mode 100644 doc/RFID_Antenna-With-Lanyard-Hook.stl diff --git a/CHANGELOG.md b/CHANGELOG.md index d5a3e315..f9e8e2ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young) - Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) - Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman) +- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman) ### Changed - Revised workflow for StandAloneMode14a (Craig Young) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 2e1a43af..8c4b45f5 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -301,39 +301,42 @@ void SendVersion(void) // measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time. // Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included. -void printUSBSpeed(uint32_t SpeedTestBufferSize) +void printUSBSpeed(void) { Dbprintf("USB Speed:"); - Dbprintf(" Sending %d bytes payload...", SpeedTestBufferSize); + Dbprintf(" Sending USB packets to client..."); + #define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds uint8_t *test_data = BigBuf_get_addr(); + uint32_t end_time; - uint32_t start_time = GetTickCount(); + uint32_t start_time = end_time = GetTickCount(); + uint32_t bytes_transferred = 0; LED_B_ON(); - for(size_t i=0; i < SpeedTestBufferSize; i += USB_CMD_DATA_SIZE) { - size_t len = MIN((SpeedTestBufferSize - i), USB_CMD_DATA_SIZE); - cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,0,len,0,test_data,len); + while(end_time < start_time + USB_SPEED_TEST_MIN_TIME) { + cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 0, USB_CMD_DATA_SIZE, 0, test_data, USB_CMD_DATA_SIZE); + end_time = GetTickCount(); + bytes_transferred += USB_CMD_DATA_SIZE; } LED_B_OFF(); - uint32_t end_time = GetTickCount(); - - Dbprintf(" Time elapsed: %dms, USB Transfer Speed PM3 -> Client = %d Bytes/s", - end_time - start_time, - 1000* SpeedTestBufferSize / (end_time - start_time)); + Dbprintf(" Time elapsed: %dms", end_time - start_time); + Dbprintf(" Bytes transferred: %d", bytes_transferred); + Dbprintf(" USB Transfer Speed PM3 -> Client = %d Bytes/s", + 1000 * bytes_transferred / (end_time - start_time)); } /** * Prints runtime information about the PM3. **/ -void SendStatus(uint32_t SpeedTestBufferSize) +void SendStatus(void) { BigBuf_print_status(); Fpga_print_status(); printConfig(); //LF Sampling config - printUSBSpeed(SpeedTestBufferSize); + printUSBSpeed(); Dbprintf("Various"); Dbprintf(" MF_DBGLEVEL........%d", MF_DBGLEVEL); Dbprintf(" ToSendMax..........%d", ToSendMax); @@ -998,6 +1001,11 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation CmdAWIDdemodFSK(c->arg[0], 0, 0, 1); break; + case CMD_VIKING_CLONE_TAG: + CopyViKingtoT55x7(c->arg[0],c->arg[1]); + break; + + #endif #ifdef WITH_HITAG @@ -1232,8 +1240,9 @@ void UsbPacketReceived(uint8_t *packet, int len) LED_B_ON(); uint8_t *BigBuf = BigBuf_get_addr(); + size_t len = 0; for(size_t i=0; iarg[1]; i += USB_CMD_DATA_SIZE) { - size_t len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE); + len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE); cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,BigBuf_get_traceLen(),BigBuf+c->arg[0]+i,len); } // Trigger a finish downloading signal with an ACK frame @@ -1269,7 +1278,7 @@ void UsbPacketReceived(uint8_t *packet, int len) SendVersion(); break; case CMD_STATUS: - SendStatus(c->arg[0]); + SendStatus(); break; case CMD_PING: cmd_send(CMD_ACK,0,0,0,0,0); diff --git a/armsrc/apps.h b/armsrc/apps.h index 5eff4511..b4cab979 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -191,6 +191,7 @@ void ReaderIClass(uint8_t arg0); void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC); void IClass_iso14443A_GetPublic(uint8_t arg0); +void CopyViKingtoT55x7(uint32_t block1,uint32_t block2); // hitag2.h void SnoopHitag(uint32_t type); void SimulateHitagTag(bool tag_mem_supplied, byte_t* data); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 862594e9..a723f502 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1047,7 +1047,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) response3a[0] = sak & 0xFB; ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); - uint8_t response5[] = { 0x01, 0x01, 0x01, 0x01 }; // Very random tag nonce + uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS: // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1 @@ -1151,9 +1151,9 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) } else if(receivedCmd[0] == 0x30) { // Received a (plain) READ uint8_t block = receivedCmd[1]; if ( tagType == 7 ) { - uint8_t start = 4 * block; + uint16_t start = 4 * block; - if ( block < 4 ) { + /*if ( block < 4 ) { //NTAG 215 uint8_t blockdata[50] = { data[0],data[1],data[2], 0x88 ^ data[0] ^ data[1] ^ data[2], @@ -1167,12 +1167,12 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) 0x00,0x00}; AppendCrc14443a(blockdata+start, 16); EmSendCmdEx( blockdata+start, MAX_MIFARE_FRAME_SIZE, false); - } else { + } else {*/ uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; emlGetMemBt( emdata, start, 16); AppendCrc14443a(emdata, 16); EmSendCmdEx(emdata, sizeof(emdata), false); - } + //} p_response = NULL; } else { @@ -1417,9 +1417,11 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) BigBuf_free_keep_EM(); LED_A_OFF(); + if (MF_DBGLEVEL >= 4){ Dbprintf("-[ Wake ups after halt [%d]", happened); Dbprintf("-[ Messages after halt [%d]", happened2); Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); + } } @@ -2194,7 +2196,7 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { nttmp1 = nt1; nttmp2 = nt2; - for (i = 1; i < 32768; i++) { + for (i = 1; i < 0xFFFF; i++) { nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i; nttmp2 = prng_successor(nttmp2, 1); @@ -2204,6 +2206,28 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { return(-99999); // either nt1 or nt2 are invalid nonces } +int32_t dist_nt_ex32(uint32_t nt1, uint32_t nt2, bool *result) { + + uint16_t i; + uint32_t nttmp1, nttmp2; + + if (nt1 == nt2) return 0; + + nttmp1 = nt1; + nttmp2 = nt2; + + *result = true; + for (i = 1; i < 0xFFFFFFFF; i++) { + nttmp1 = prng_successor(nttmp1, 1); + if (nttmp1 == nt2) return i; + + nttmp2 = prng_successor(nttmp2, 1); + if (nttmp2 == nt1) return -i; + } + + *result = false; + return(-99999); // either nt1 or nt2 are invalid nonces +} //----------------------------------------------------------------------------- // Recover several bits of the cypher stream. This implements (first stages of) @@ -2244,6 +2268,7 @@ void ReaderMifare(bool first_try) byte_t par_list[8] = {0x00}; byte_t ks_list[8] = {0x00}; + #define PRNG_SEQUENCE_LENGTH (1 << 16); static uint32_t sync_time = 0; static uint32_t sync_cycles = 0; int catch_up_cycles = 0; @@ -2254,7 +2279,7 @@ void ReaderMifare(bool first_try) if (first_try) { mf_nr_ar3 = 0; sync_time = GetCountSspClk() & 0xfffffff8; - sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + sync_cycles = PRNG_SEQUENCE_LENGTH; //65536; //0x10000 // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). nt_attacked = 0; nt = 0; par[0] = 0; @@ -2271,8 +2296,12 @@ void ReaderMifare(bool first_try) LED_C_OFF(); - #define DARKSIDE_MAX_TRIES 32 // number of tries to sync on PRNG cycle. Then give up. - uint16_t unsuccessfull_tries = 0; + #define MAX_UNEXPECTED_RANDOM 5 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. + #define MAX_SYNC_TRIES 16 + uint16_t unexpected_random = 0; + uint16_t sync_tries = 0; + int16_t debug_info_nr = -1; + uint32_t debug_info[MAX_SYNC_TRIES]; for(uint16_t i = 0; TRUE; i++) { @@ -2290,16 +2319,20 @@ void ReaderMifare(bool first_try) continue; } - sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; - catch_up_cycles = 0; + if (debug_info_nr == -1) { + sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; + catch_up_cycles = 0; - // if we missed the sync time already, advance to the next nonce repeat - while(GetCountSspClk() > sync_time) { - sync_time = (sync_time & 0xfffffff8) + sync_cycles; - } + // if we missed the sync time already, advance to the next nonce repeat + while(GetCountSspClk() > sync_time) { + sync_time = (sync_time & 0xfffffff8) + sync_cycles; + } - // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) - ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) + ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + } else { + ReaderTransmit(mf_auth, sizeof(mf_auth), NULL); + } // Receive the (4 Byte) "random" nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) { @@ -2317,19 +2350,32 @@ void ReaderMifare(bool first_try) int nt_distance = dist_nt(previous_nt, nt); if (nt_distance == 0) { nt_attacked = nt; - } - else { + } else { if (nt_distance == -99999) { // invalid nonce received - unsuccessfull_tries++; - if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) { + unexpected_random++; + if (!nt_attacked && unexpected_random > MAX_UNEXPECTED_RANDOM) { isOK = -3; // Card has an unpredictable PRNG. Give up break; } else { continue; // continue trying... } } + if (++sync_tries > MAX_SYNC_TRIES) { + if (sync_tries > 2 * MAX_SYNC_TRIES) { + isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } else { // continue for a while, just to collect some debug info + debug_info[++debug_info_nr] = nt_distance; + continue; + } + } sync_cycles = (sync_cycles - nt_distance); - if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); + if (sync_cycles <= 0) { + sync_cycles += PRNG_SEQUENCE_LENGTH; + } + if (MF_DBGLEVEL >= 3) { + Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); + } continue; } } @@ -2401,8 +2447,15 @@ void ReaderMifare(bool first_try) mf_nr_ar[3] &= 0x1F; - byte_t buf[28] = {0x00}; + if (isOK == -4) { + if (MF_DBGLEVEL >= 3) { + for(uint16_t i = 0; i < MAX_SYNC_TRIES; i++) { + Dbprintf("collected debug info[%d] = %d\n", i, debug_info[i]); + } + } + } + byte_t buf[28]; memcpy(buf + 0, uid, 4); num_to_bytes(nt, 4, buf + 4); memcpy(buf + 8, par_list, 8); @@ -2418,8 +2471,7 @@ void ReaderMifare(bool first_try) set_tracing(FALSE); } - - /* +/** *MIFARE 1K simulate. * *@param flags : diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 3c7a544e..8feaa6ae 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -90,9 +90,9 @@ void ReadTItag(void) // when we read a TI tag we sample the zerocross line at 2Mhz // TI tags modulate a 1 as 16 cycles of 123.2Khz // TI tags modulate a 0 as 16 cycles of 134.2Khz - #define FSAMPLE 2000000 - #define FREQLO 123200 - #define FREQHI 134200 + #define FSAMPLE 2000000 + #define FREQLO 123200 + #define FREQHI 134200 signed char *dest = (signed char *)BigBuf_get_addr(); uint16_t n = BigBuf_max_traceLen(); @@ -1080,14 +1080,14 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) */ /* T55x7 configuration register definitions */ -#define T55x7_POR_DELAY 0x00000001 -#define T55x7_ST_TERMINATOR 0x00000008 -#define T55x7_PWD 0x00000010 +#define T55x7_POR_DELAY 0x00000001 +#define T55x7_ST_TERMINATOR 0x00000008 +#define T55x7_PWD 0x00000010 #define T55x7_MAXBLOCK_SHIFT 5 -#define T55x7_AOR 0x00000200 -#define T55x7_PSKCF_RF_2 0 -#define T55x7_PSKCF_RF_4 0x00000400 -#define T55x7_PSKCF_RF_8 0x00000800 +#define T55x7_AOR 0x00000200 +#define T55x7_PSKCF_RF_2 0 +#define T55x7_PSKCF_RF_4 0x00000400 +#define T55x7_PSKCF_RF_8 0x00000800 #define T55x7_MODULATION_DIRECT 0 #define T55x7_MODULATION_PSK1 0x00001000 #define T55x7_MODULATION_PSK2 0x00002000 @@ -1098,17 +1098,18 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) #define T55x7_MODULATION_FSK2a 0x00007000 #define T55x7_MODULATION_MANCHESTER 0x00008000 #define T55x7_MODULATION_BIPHASE 0x00010000 -#define T55x7_BITRATE_RF_8 0 -#define T55x7_BITRATE_RF_16 0x00040000 -#define T55x7_BITRATE_RF_32 0x00080000 -#define T55x7_BITRATE_RF_40 0x000C0000 -#define T55x7_BITRATE_RF_50 0x00100000 -#define T55x7_BITRATE_RF_64 0x00140000 +//#define T55x7_MODULATION_BIPHASE57 0x00011000 +#define T55x7_BITRATE_RF_8 0 +#define T55x7_BITRATE_RF_16 0x00040000 +#define T55x7_BITRATE_RF_32 0x00080000 +#define T55x7_BITRATE_RF_40 0x000C0000 +#define T55x7_BITRATE_RF_50 0x00100000 +#define T55x7_BITRATE_RF_64 0x00140000 #define T55x7_BITRATE_RF_100 0x00180000 #define T55x7_BITRATE_RF_128 0x001C0000 /* T5555 (Q5) configuration register definitions */ -#define T5555_ST_TERMINATOR 0x00000001 +#define T5555_ST_TERMINATOR 0x00000001 #define T5555_MAXBLOCK_SHIFT 0x00000001 #define T5555_MODULATION_MANCHESTER 0 #define T5555_MODULATION_PSK1 0x00000010 @@ -1118,22 +1119,23 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) #define T5555_MODULATION_FSK2 0x00000050 #define T5555_MODULATION_BIPHASE 0x00000060 #define T5555_MODULATION_DIRECT 0x00000070 -#define T5555_INVERT_OUTPUT 0x00000080 -#define T5555_PSK_RF_2 0 -#define T5555_PSK_RF_4 0x00000100 -#define T5555_PSK_RF_8 0x00000200 -#define T5555_USE_PWD 0x00000400 -#define T5555_USE_AOR 0x00000800 -#define T5555_BITRATE_SHIFT 12 -#define T5555_FAST_WRITE 0x00004000 -#define T5555_PAGE_SELECT 0x00008000 +#define T5555_INVERT_OUTPUT 0x00000080 +#define T5555_PSK_RF_2 0 +#define T5555_PSK_RF_4 0x00000100 +#define T5555_PSK_RF_8 0x00000200 +#define T5555_USE_PWD 0x00000400 +#define T5555_USE_AOR 0x00000800 +#define T5555_BITRATE_SHIFT 12 +#define T5555_FAST_WRITE 0x00004000 +#define T5555_PAGE_SELECT 0x00008000 /* * Relevant times in microsecond * To compensate antenna falling times shorten the write times * and enlarge the gap ones. */ -#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc) + +#define START_GAP 50*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 @@ -1157,7 +1159,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) // Write one bit to card void T55xxWriteBit(int bit) { - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + //FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); if (!bit) @@ -1176,7 +1178,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod // Set up FPGA, 125kHz // Wait for config.. (192+8190xPOW)x8 == 67ms LFSetupFPGAForADC(0, true); - + // Now start writting FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelayUs(START_GAP); @@ -1211,7 +1213,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod void TurnReadLFOn(){ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // Give it a bit of time for the resonant antenna to settle. - SpinDelayUs(8*150); + SpinDelayUs(300); } @@ -1229,7 +1231,21 @@ void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode) // Set up FPGA, 125kHz // Wait for config.. (192+8190xPOW)x8 == 67ms - LFSetupFPGAForADC(0, true); + //LFSetupFPGAForADC(0, true); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + + // Connect the A/D to the peak-detected low-frequency path. + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + + // Now set up the SSC to get the ADC samples that are now streaming at us. + FpgaSetupSsc(); + + // Give it a bit of time for the resonant antenna to settle. + //SpinDelayUs(8*200); //192FC + SpinDelay(50); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelayUs(START_GAP); @@ -2098,3 +2114,14 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } +void CopyViKingtoT55x7(uint32_t block1,uint32_t block2) +{ + LED_D_ON(); + T55xxWriteBlock(block1,1,0,0); + T55xxWriteBlock(block2,2,0,0); + + T55xxWriteBlock(T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 2 << T5555_MAXBLOCK_SHIFT,0,0,1); + LED_D_OFF(); + DbpString("DONE!"); +} + diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 13c4a5b8..f63d754d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -908,7 +908,8 @@ void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - emlSetMem(datain, arg0, arg1); // data, block num, blocks count + //emlSetMem(datain, arg0, arg1); // data, block num, blocks count + emlSetMem_xt(datain, arg0, arg1, arg2); // data, block num, blocks count, block byte width } void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index c9ff8c64..eab8a930 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -272,7 +272,7 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL); - //len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL); + if (len != 4) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); return 0; @@ -556,8 +556,12 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) // work with emulator memory void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { + emlSetMem_xt(data, blockNum, blocksCount, 16); +} + +void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) { uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(emCARD + blockNum * 16, data, blocksCount * 16); + memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth); } void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index bf965d40..1dd77ed8 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -90,6 +90,7 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo); // emulator functions void emlClearMem(void); void emlSetMem(uint8_t *data, int blockNum, int blocksCount); +void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); void emlGetMem(uint8_t *data, int blockNum, int blocksCount); void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount); uint64_t emlGetKey(int sectorNum, int keyType); diff --git a/armsrc/util.c b/armsrc/util.c index 1dd8dc75..3d536f39 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -345,7 +345,9 @@ void StartCountUS() } uint32_t RAMFUNC GetCountUS(){ - return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10); + //return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10); + // By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548 + return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV * 2) / 3); } static uint32_t GlobalUsCounter = 0; diff --git a/bootrom/Makefile b/bootrom/Makefile index 92373995..146bfe4f 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -8,7 +8,9 @@ # DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code ARMSRC = -THUMBSRC = cmd.c usb_cdc.c bootrom.c +THUMBSRC = cmd.c \ + usb_cdc.c \ + bootrom.c ASMSRC = ram-reset.s flash-reset.s ## There is a strange bug with the linker: Sometimes it will not emit the glue to call diff --git a/client/Makefile b/client/Makefile index de7bd45a..bcd59397 100644 --- a/client/Makefile +++ b/client/Makefile @@ -119,6 +119,7 @@ CMDSRCS = nonce2key/crapto1.c\ cmdlfem4x.c \ cmdlfhitag.c \ cmdlfti.c \ + cmdlfviking.c\ cmdparser.c \ cmdmain.c \ cmdlft55xx.c \ @@ -130,6 +131,7 @@ CMDSRCS = nonce2key/crapto1.c\ aes.c\ protocols.c\ sha1.c\ + sha256.c\ cmdcrc.c\ reveng/reveng.c\ reveng/cli.c\ diff --git a/client/cmddata.c b/client/cmddata.c index f3644304..010bf73c 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -24,6 +24,7 @@ #include "usb_cmd.h" #include "crc.h" #include "crc16.h" +#include "loclass/cipherutils.h" uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; uint8_t g_debugMode=0; @@ -1881,6 +1882,54 @@ int CmdRawDemod(const char *Cmd) return ans; } +int AmVikingDecode(const uint8_t *id){ + // searching the buffer for the id + //uint8_t id_bits[32]; + // convert 4 bytes of id to 32 bits present in 32 bytes data; + //bytes_to_bits(id,4,id_bits,sizeof(id_bits)); + + //print_arraybinary(id_bits,sizeof(id_bits)); + PrintAndLog(" binary: %s", printBits(4, id) ); + + //size_t idx = 0; + size_t BitLen = DemodBufferLen; + uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; + memcpy(BitStream, DemodBuffer, BitLen); + + // if (VikingDecode(BitStream,BitLen,&idx,id_bits,sizeof(id_bits)) == 1) + // { + // setDemodBuf(BitStream,64, idx); + // PrintAndLog("Found Viking tag\n"); + // CmdPrintDemodBuff("x"); + // } + // else + // { + // PrintAndLog("Not found Viking tag\n"); + // } + return 0; +} +int AMVikingDemod(const uint8_t *id){ + // demod am clock 32 fail + if (!ASKDemod("32",g_debugMode,false,1)) + return 0; + // search for the card id from bitstream. + return AmVikingDecode(id); +} +//by Gusto +// takes 1 argument <8 bytes of Hex number on the card +// print binary found and saves in grapbuffer for further commands +int CmdAMVikingDemod(const char *Cmd){ + uint8_t id[4]; + if (param_gethex(Cmd,0,id,8) == 1) + { + PrintAndLog("Usage: data vikingdemod CardID 8 bytes of hex number"); + return 0; + } + PrintAndLog("Card ID : %02X%02X%02X%02X\n",id[0],id[1],id[2],id[3]); + // try to demod AMViking + return AMVikingDemod(id); +} + int CmdGrid(const char *Cmd) { sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); @@ -1954,11 +2003,6 @@ int CmdHpf(const char *Cmd) RepaintGraphWindow(); return 0; } -typedef struct { - uint8_t * buffer; - uint32_t numbits; - uint32_t position; -} BitstreamOut; bool _headBit( BitstreamOut *stream) { @@ -2276,6 +2320,99 @@ int CmdZerocrossings(const char *Cmd) return 0; } +int usage_data_bin2hex(){ + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); + return 0; +} + +/** + * @brief Utility for conversion via cmdline. + * @param Cmd + * @return + */ +int Cmdbin2hex(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_bin2hex(); + } + //Number of digits supplied as argument + size_t length = en - bg +1; + size_t bytelen = (length+7) / 8; + uint8_t* arr = (uint8_t *) malloc(bytelen); + memset(arr, 0, bytelen); + BitstreamOut bout = { arr, 0, 0 }; + + for(; bg <= en ;bg++) + { + char c = Cmd[bg]; + if( c == '1') pushBit(&bout, 1); + else if( c == '0') pushBit(&bout, 0); + else PrintAndLog("Ignoring '%c'", c); + } + + if(bout.numbits % 8 != 0) + { + printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8)); + } + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + for(size_t x = 0; x < bytelen ; x++) + { + printf("%02X", arr[x]); + } + printf("\n"); + free(arr); + return 0; +} + +int usage_data_hex2bin(){ + + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); + return 0; + +} + +int Cmdhex2bin(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_hex2bin(); + } + + + while(bg <= en ) + { + char x = Cmd[bg++]; + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else + continue; + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + + for(int i= 0 ; i < 4 ; ++i) + printf("%d",(x >> (3 - i)) & 1); + } + printf("\n"); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -2284,12 +2421,14 @@ static command_t CommandTable[] = {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"}, {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, + {"bin2hex", Cmdbin2hex, 1, "bin2hex -- Converts binary to hexadecimal"}, {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, {"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"}, + {"vikingdemod", CmdAMVikingDemod, 1, "Demodulate a Viking AM 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"}, {"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"}, @@ -2298,6 +2437,7 @@ static command_t CommandTable[] = {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, + {"hex2bin", Cmdhex2bin, 1, "hex2bin -- Converts hexadecimal to binary"}, {"hide", CmdHide, 1, "Hide graph window"}, {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, {"load", CmdLoad, 1, " -- Load trace (to graph window"}, diff --git a/client/cmddata.h b/client/cmddata.h index fcc51a6b..c70f938e 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -67,7 +67,8 @@ int PSKDemod(const char *Cmd, bool verbose); int NRZrawDemod(const char *Cmd, bool verbose); void printEM410x(uint32_t hi, uint64_t id); int getSamples(const char *Cmd, bool silent); - +int AMVikingDemod(const uint8_t *cardid); +int CmdAMVikingDemod(const char *cmd); #define MAX_DEMOD_BUF_LEN (1024*128) extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; diff --git a/client/cmdhf.c b/client/cmdhf.c index 91743c46..4a871586 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -531,7 +531,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 (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); } else { diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 83310a54..76fd1b7e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -34,7 +34,7 @@ start: SendCommand(&c); //flush queue - while (ukbhit()) getchar(); + while (ukbhit()) getchar(); // wait cycle while (true) { @@ -59,6 +59,7 @@ start: case -1 : PrintAndLog("Button pressed. Aborted.\n"); break; case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break; case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break; + case -4 : PrintAndLog("The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). This needs to be fixed.\n"); break; default: ; } break; @@ -80,7 +81,7 @@ start: } else { isOK = 0; printf("------------------------------------------------------------------\n"); - PrintAndLog("Found valid key:%012"llx" \n", r_key); + PrintAndLog("Found valid key: %012"llx" \n", r_key); } PrintAndLog(""); @@ -1210,13 +1211,13 @@ int CmdHF14AMfELoad(const char *Cmd) uint8_t buf8[64] = {0x00}; int i, len, blockNum, numBlocks; int nameParamNo = 1; - + uint8_t blockWidth = 32; char ctmp = param_getchar(Cmd, 0); if ( ctmp == 'h' || ctmp == 0x00) { PrintAndLog("It loads emul dump from the file `filename.eml`"); PrintAndLog("Usage: hf mf eload [card memory] "); - PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL"); PrintAndLog(""); PrintAndLog(" sample: hf mf eload filename"); PrintAndLog(" hf mf eload 4 filename"); @@ -1229,6 +1230,8 @@ int CmdHF14AMfELoad(const char *Cmd) case '\0': numBlocks = 16*4; break; case '2' : numBlocks = 32*4; break; case '4' : numBlocks = 256; break; + case 'U' : // fall through + case 'u' : numBlocks = 255; blockWidth = 8; break; default: { numBlocks = 16*4; nameParamNo = 0; @@ -1263,19 +1266,18 @@ int CmdHF14AMfELoad(const char *Cmd) return 2; } - if (strlen(buf) < 32){ + if (strlen(buf) < blockWidth){ if(strlen(buf) && feof(f)) break; - PrintAndLog("File content error. Block data must include 32 HEX symbols"); + PrintAndLog("File content error. Block data must include %d HEX symbols", blockWidth); fclose(f); return 2; } - for (i = 0; i < 32; i += 2) { + for (i = 0; i < blockWidth; i += 2) { sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]); } - - if (mfEmlSetMem(buf8, blockNum, 1)) { + if (mfEmlSetMem_xt(buf8, blockNum, 1, blockWidth/2)) { PrintAndLog("Cant set emul block: %3d", blockNum); fclose(f); return 3; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 41ee59c1..f6905b24 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -58,12 +58,21 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { }; #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_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS}; +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_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); @@ -799,6 +808,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } + // Read signature if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) { uint8_t ulev1_signature[32] = {0x00}; status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); @@ -814,6 +824,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } + // Get Version if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) { uint8_t version[10] = {0x00}; status = ulev1_getVersion(version, sizeof(version)); diff --git a/client/cmdhw.c b/client/cmdhw.c index 16be8bbe..03f4186f 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -405,6 +405,7 @@ int CmdTune(const char *Cmd) int CmdVersion(const char *Cmd) { + clearCommandBuffer(); UsbCommand c = {CMD_VERSION}; static UsbCommand resp = {0, {0, 0, 0}}; @@ -430,13 +431,11 @@ int CmdStatus(const char *Cmd) { uint8_t speed_test_buffer[USB_CMD_DATA_SIZE]; sample_buf = speed_test_buffer; - #define USB_SPEED_TEST_SIZE (100*USB_CMD_DATA_SIZE) clearCommandBuffer(); - UsbCommand c = {CMD_STATUS, {USB_SPEED_TEST_SIZE}}; + UsbCommand c = {CMD_STATUS}; SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) { PrintAndLog("Status command failed. USB Speed Test timed out"); } return 0; @@ -449,40 +448,39 @@ int CmdPing(const char *Cmd) UsbCommand resp; UsbCommand c = {CMD_PING}; SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) PrintAndLog("Ping successfull"); - }else{ - PrintAndLog("Ping failed"); - } - return 0; + else + PrintAndLog("Ping failed"); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, - {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, - {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, - {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, - {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, - {"reset", CmdReset, 0, "Reset the Proxmark3"}, - {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, - {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, - {"tune", CmdTune, 0, "Measure antenna tuning"}, - {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, + {"help", CmdHelp, 1, "This help"}, + {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, + {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, + {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, + {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, + {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, + {"reset", CmdReset, 0, "Reset the Proxmark3"}, + {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, + {"tune", CmdTune, 0, "Measure antenna tuning"}, + {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, {"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"}, {"ping", CmdPing, 0, "Test if the pm3 is responsive"}, - {NULL, NULL, 0, NULL} + {NULL, NULL, 0, NULL} }; int CmdHW(const char *Cmd) { - CmdsParse(CommandTable, Cmd); - return 0; + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdlf.c b/client/cmdlf.c index 809602a3..db08310a 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -30,22 +30,69 @@ #include "cmdlfpcf7931.h" #include "cmdlfio.h" #include "lfdemod.h" - +#include "cmdlfviking.h" static int CmdHelp(const char *Cmd); + +int usage_lf_cmdread() +{ + PrintAndLog("Usage: lf cmdread [H] "); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" L Low frequency (125 KHz)"); + PrintAndLog(" H High frequency (134 KHz)"); + PrintAndLog(" H delay OFF"); + PrintAndLog(" H time period ZERO"); + PrintAndLog(" H time period ONE"); + PrintAndLog("Examples:"); + PrintAndLog(" lf cmdread 80 100 200 11000"); + PrintAndLog(" lf cmdread 80 100 100 11000 H"); + return 0; +} + /* send a command before reading */ int CmdLFCommandRead(const char *Cmd) { - static char dummy[3]; + static char dummy[3] = {0x20,0x00,0x00}; + bool errors = FALSE; + uint8_t divisor = 0; //125khz + uint8_t cmdp =0; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + return usage_lf_cmdread(); + case 'H': + divisor = 88; + cmdp++; + break; + case 'a': + //param_getchar(Cmd, cmdp+1) == '1'; + cmdp+=2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = 1; + break; + } + if(errors) break; + } + // No args + if(cmdp == 0) errors = 1; - dummy[0]= ' '; + //Validations + if(errors) return usage_lf_cmdread(); + + UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K}; + sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1)); + // in case they specified 'h' + strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); - UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K}; - sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1)); - // in case they specified 'h' - strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); - SendCommand(&c); - return 0; + PrintAndLog("ICE: %d %s -- %s", strlen((char *)c.d.asBytes) ,dummy, c.d.asBytes); + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdFlexdemod(const char *Cmd) @@ -1074,7 +1121,7 @@ int CmdLFfind(const char *Cmd) ans=CmdG_Prox_II_Demod(""); if (ans>0) { - PrintAndLog("\nValid G Prox II ID Found!"); + PrintAndLog("\nValid Guardall G-Prox II ID Found!"); return 1; } @@ -1165,7 +1212,7 @@ static command_t CommandTable[] = {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"}, {"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, {"t55xx", CmdLFT55XX, 1, "{ T55X7 RFIDs... }"}, - +{"viking", CmdLFViking, 1, "{ Viking RFIDs... }"}, {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"}, {"cmdread", CmdLFCommandRead, 0, " <'0' period> <'1' period> ['h' 134] \n\t\t-- Modulate LF reader field to send command before read (all periods in microseconds)"}, diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 605559ac..5dc5bbee 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -368,6 +368,7 @@ bool tryDetectModulation(){ } } else { clk = GetAskClock("", FALSE, FALSE); + if (clk>0) { sprintf(cmdStr,"%d", clk/2); CmdLtrim(cmdStr); diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 364f0271..37895fe8 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -10,6 +10,26 @@ #ifndef CMDLFT55XX_H__ #define CMDLFT55XX_H__ +// config blocks +#define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // compat mode, data rate 32, manchester, ST, 7 data blocks +#define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // compat mode, data rate 32, manchester, 7 data blocks + +#define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // emulate em4x02/unique - compat mode, manchester, data rate 64, 2 data blocks + + +// FDXB requires data inversion and BiPhase 57 is simply BipHase 50 inverted, so we can either do it using the modulation scheme or the inversion flag +// we've done both below to prove that it works either way, and the modulation value for BiPhase 50 in the Atmel data sheet of binary "10001" (17) is a typo, +// and it should actually be "10000" (16) +// #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks +#define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks +#define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks +#define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2 +#define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7 +#define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks +#define T55X7_VIKING_CONFIG_BLOCK 0x00088040 // compat mode, data rate 32, Manchester, 2 data blocks +#define T55X7_bin 0b0010 + + typedef struct { enum { DEMOD_NRZ = 0x00, diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c new file mode 100644 index 00000000..f888ba8b --- /dev/null +++ b/client/cmdlfviking.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "cmdlfviking.h" +#include "lfdemod.h" +static int CmdHelp(const char *Cmd); +int CmdVikingDemod(const char *Cmd) +{ + uint8_t id[4]; + if (param_gethex(Cmd,0,id,8) == 1) + { + PrintAndLog("Usage: lf viking demod "); + return 0; + } + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {false,0,0}}; + SendCommand(&c); + WaitForResponse(CMD_ACK,NULL); + getSamples("40000",true); + // try to demod AMViking + return AMVikingDemod(id); +} +int CmdVikingClone(const char *Cmd) +{ + uint32_t b1,b2; + // get the tag number 64 bits (8 bytes) in hex + uint8_t id[8]; + if (param_gethex(Cmd,0,id,16) == 1) + { + PrintAndLog("Usage: lf viking clone "); + return 0; + } + b1 = bytes_to_num(id,sizeof(uint32_t)); + b2 = bytes_to_num(id + sizeof(uint32_t),sizeof(uint32_t)); + UsbCommand c = {CMD_VIKING_CLONE_TAG,{b1,b2}}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"demod",CmdVikingDemod ,1, "<8 digits tag id> -- Extract tag data"}, + {"clone", CmdVikingClone, 1, "<16 digits card data> clone viking tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFViking(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h new file mode 100644 index 00000000..469a2b7b --- /dev/null +++ b/client/cmdlfviking.h @@ -0,0 +1,7 @@ +#ifndef CMDLFVIKING_H__ +#define CMDLFVIKING_H__ +int CmdLFViking(const char *Cmd); +int CmdVikingDemod(const char *Cmd); +int CmdVikingClone(const char *Cmd); +#endif + diff --git a/client/cmdmain.c b/client/cmdmain.c index f0963d1e..b0e1b2ef 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -36,6 +36,7 @@ static int CmdRev(const char *Cmd); static int CmdLS(const char *Cmd); //For storing command that are received from the device +#define CMD_BUFFER_SIZE 50 static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; //Points to the next empty position to write to static int cmd_head;//Starts as 0 @@ -149,9 +150,9 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou response = &resp; // Wait until the command is received - for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { + for ( size_t dm_seconds = 0; dm_seconds < ms_timeout/10; dm_seconds++ ) { - while(getCommand(response)) { + while( getCommand(response) ) { if(response->cmd == cmd){ return true; } @@ -166,7 +167,7 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou } bool WaitForResponse(uint32_t cmd, UsbCommand* response) { - return WaitForResponseTimeout(cmd,response,-1); + return WaitForResponseTimeout(cmd, response, -1); } //----------------------------------------------------------------------------- @@ -203,8 +204,10 @@ void UsbCommandReceived(UsbCommand *UC) return; } break; - default: break; - } + default: storeCommand(UC); + break; + } + } diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index c77477e8..93715563 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -98,6 +98,7 @@ typedef struct{ #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 +#define CMD_VIKING_CLONE_TAG 0x0222 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index fdc2b18d..96805e43 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -56,7 +56,8 @@ local _commands = { CMD_ASK_SIM_TAG = 0x021F, CMD_PSK_SIM_TAG = 0x0220, CMD_AWID_DEMOD_FSK = 0x0221, - + CMD_VIKING_CLONE_TAG = 0x0222, + --/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ --// For the 13.56 MHz tags @@ -198,7 +199,7 @@ Command = { return o end, parse = function(packet) - local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH512', packet) + local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet) return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data} end diff --git a/client/mifarehost.c b/client/mifarehost.c index 6acd22f8..d3f4a4cd 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -93,16 +93,16 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo return resp.arg[0]; // error during nested } - memcpy(&uid, resp.d.asBytes, 4); + memcpy(&uid, resp.d.asBytes, 4); PrintAndLog("uid:%08x trgbl=%d trgkey=%x", uid, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8); - for (i = 0; i < 2; i++) { - statelists[i].blockNo = resp.arg[2] & 0xff; - statelists[i].keyType = (resp.arg[2] >> 8) & 0xff; - statelists[i].uid = uid; - memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4); - memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4); - } + for (i = 0; i < 2; i++) { + statelists[i].blockNo = resp.arg[2] & 0xff; + statelists[i].keyType = (resp.arg[2] >> 8) & 0xff; + statelists[i].uid = uid; + memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4); + memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4); + } // calc keys @@ -190,8 +190,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo } free(statelists[0].head.slhead); - free(statelists[1].head.slhead); - + free(statelists[1].head.slhead); return 0; } @@ -201,8 +200,9 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}}; memcpy(c.d.asBytes, keyBlock, 6 * keycnt); + + clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) return 1; if ((resp.arg[0] & 0xff) != 0x01) return 2; @@ -214,8 +214,8 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) { UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}}; + clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1; memcpy(data, resp.d.asBytes, blocksCount * 16); @@ -223,8 +223,14 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) { } int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) { - UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}}; - memcpy(c.d.asBytes, data, blocksCount * 16); + return mfEmlSetMem_xt(data, blockNum, blocksCount, 16); +} + +int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) { + UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, blockBtWidth}}; + memcpy(c.d.asBytes, data, blocksCount * blockBtWidth); + + clearCommandBuffer(); SendCommand(&c); return 0; } @@ -264,8 +270,9 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin uint8_t isOK = 0; UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}}; memcpy(c.d.asBytes, data, 16); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { isOK = resp.arg[0] & 0xff; @@ -284,9 +291,10 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { uint8_t isOK = 0; UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}}; + + clearCommandBuffer(); SendCommand(&c); - - UsbCommand resp; + UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { isOK = resp.arg[0] & 0xff; memcpy(data, resp.d.asBytes, 16); diff --git a/client/mifarehost.h b/client/mifarehost.h index f6ffab3f..e2903ff8 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -54,6 +54,7 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t key int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); +int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe); int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params); diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index 919c0a3e..c013c85d 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -29,50 +29,48 @@ int compar_state(const void * a, const void * b) { } int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key) { - struct Crypto1State *state; - uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2; - byte_t bt, ks3x[8], par[8][8]; - uint64_t key_recovered; - int64_t *state_s; - static uint32_t last_uid; - static int64_t *last_keylist; - rr = 0; + struct Crypto1State *state; + uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2; + byte_t bt, ks3x[8], par[8][8]; + uint64_t key_recovered; + int64_t *state_s; + static uint32_t last_uid; + static int64_t *last_keylist; + rr = 0; - if (last_uid != uid && last_keylist != NULL) - { - free(last_keylist); - last_keylist = NULL; - } - last_uid = uid; + if (last_uid != uid && last_keylist != NULL) { + free(last_keylist); + last_keylist = NULL; + } + last_uid = uid; - // Reset the last three significant bits of the reader nonce - nr &= 0xffffff1f; + // Reset the last three significant bits of the reader nonce + nr &= 0xffffff1f; - PrintAndLog("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx") nr(%08"llx")\n\n",uid,nt,par_info,ks_info,nr); + PrintAndLog("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx") nr(%08"llx")\n\n", uid, nt, par_info, ks_info, nr); + + for (pos=0; pos<8; pos++) { + ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f; + bt = (par_info >> (pos*8)) & 0xff; + for (i=0; i<8; i++) { + par[7-pos][i] = (bt >> i) & 0x01; + } + } - for (pos=0; pos<8; pos++) - { - ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f; - bt = (par_info >> (pos*8)) & 0xff; - for (i=0; i<8; i++) - { - par[7-pos][i] = (bt >> i) & 0x01; - } - } + printf("|diff|{nr} |ks3|ks3^5|parity |\n"); + printf("+----+--------+---+-----+---------------+\n"); + for (i=0; i<8; i++) { + nr_diff = nr | i << 5; + printf("| %02x |%08x|", i << 5, nr_diff); + printf(" %01x | %01x |", ks3x[i], ks3x[i]^5); + for (pos=0; pos<7; pos++) + printf("%01x,", par[i][pos]); + printf("%01x|\n", par[i][7]); + } + printf("+----+--------+---+-----+---------------+\n"); - printf("|diff|{nr} |ks3|ks3^5|parity |\n"); - printf("+----+--------+---+-----+---------------+\n"); - for (i=0; i<8; i++) - { - nr_diff = nr | i << 5; - printf("| %02x |%08x|",i << 5, nr_diff); - printf(" %01x | %01x |",ks3x[i], ks3x[i]^5); - for (pos=0; pos<7; pos++) printf("%01x,", par[i][pos]); - printf("%01x|\n", par[i][7]); - } - - if (par_info==0) - PrintAndLog("parity is all zero,try special attack!just wait for few more seconds..."); + if ( par_info == 0 ) + PrintAndLog("Parity is all zero, try special attack! Wait for few more seconds..."); state = lfsr_common_prefix(nr, rr, ks3x, par, par_info==0); state_s = (int64_t*)state; @@ -97,56 +95,58 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_ *(state_s + i) = -1; //Create the intersection: - if (par_info == 0 ) - if ( last_keylist != NULL) - { + if (par_info == 0 ) { + if ( last_keylist != NULL) { int64_t *p1, *p2, *p3; p1 = p3 = last_keylist; p2 = state_s; while ( *p1 != -1 && *p2 != -1 ) { if (compar_state(p1, p2) == 0) { - printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",(uint64_t)(p1-last_keylist),(uint64_t)(p2-state_s),(uint64_t)(p3-last_keylist),*p1); + printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n", + (uint64_t)(p1-last_keylist), + (uint64_t)(p2-state_s), + (uint64_t)(p3-last_keylist), + *p1); *p3++ = *p1++; p2++; - } - else { + } else { while (compar_state(p1, p2) == -1) ++p1; while (compar_state(p1, p2) == 1) ++p2; } } - key_count = p3 - last_keylist;; - } - else + key_count = p3 - last_keylist; + } else { key_count = 0; - else - { + } + } else { last_keylist = state_s; key_count = i; } - printf("key_count:%d\n", key_count); + printf("key candidates count: %d\n", key_count); // The list may still contain several key candidates. Test each of them with mfCheckKeys + int res; + uint8_t keyBlock[6]; + uint64_t key64; for (i = 0; i < key_count; i++) { - uint8_t keyBlock[6]; - uint64_t key64; + key64 = *(last_keylist + i); num_to_bytes(key64, 6, keyBlock); key64 = 0; - if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) { + res = mfCheckKeys(0, 0, false, 1, keyBlock, &key64); + if (!res) { *key = key64; free(last_keylist); last_keylist = NULL; - if (par_info ==0) + if (par_info == 0) free(state); return 0; } } - free(last_keylist); last_keylist = state_s; - return 1; } @@ -243,7 +243,6 @@ int tryMfk32_moebius(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){ return isSuccess; } - int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){ struct Crypto1State *revstate; diff --git a/client/scripts/dumptoemul-mfu.lua b/client/scripts/dumptoemul-mfu.lua new file mode 100644 index 00000000..bdcc667b --- /dev/null +++ b/client/scripts/dumptoemul-mfu.lua @@ -0,0 +1,122 @@ +-- The getopt-functionality is loaded from pm3/getopt.lua +-- Have a look there for further details +getopt = require('getopt') +bin = require('bin') + +example = "script run dumptoemul -i dumpdata-foobar.bin" +author = "Martin Holst Swende" +usage = "script run dumptoemul [-i ] [-o ]" +desc =[[ +This script takes a dumpfile from 'hf mf dump' and converts it to a format that can be used +by the emulator + +Arguments: + -h This help + -i Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used + -o Specifies the output file. If omitted, .eml is used. + +]] + +------------------------------- +-- Some utilities +------------------------------- + +--- +-- 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) +end + + +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end + +local function convert_to_ascii(hexdata) + if string.len(hexdata) % 8 ~= 0 then + return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata))) + end + + local js,i = "["; + for i = 1, string.len(hexdata),8 do + js = js .."'" ..string.sub(hexdata,i,i+7).."',\n" + end + js = js .. "]" + return js +end + +local function readdump(infile) + t = infile:read("*all") + --print(string.len(t)) + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + --print(len,hex) + return hex +end + +local function convert_to_emulform(hexdata) + if string.len(hexdata) % 8 ~= 0 then + return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata))) + end + local ascii,i = ""; + for i = 1, string.len(hexdata),8 do + ascii = ascii ..string.sub(hexdata,i,i+7).."\n" + end + + return string.sub(ascii,1,-1) +end + +local function main(args) + + local input = "dumpdata.bin" + local output + + for o, a in getopt.getopt(args, 'i:o:h') do + if o == "h" then return help() end + if o == "i" then input = a end + if o == "o" then output = a end + end + -- Validate the parameters + + local infile = io.open(input, "rb") + if infile == nil then + return oops("Could not read file ", input) + end + local dumpdata = readdump(infile) + -- The hex-data is now in ascii-format, + + -- But first, check the uid + local uid = string.sub(dumpdata,1,8) + output = output or (uid .. ".eml") + + -- Format some linebreaks + dumpdata = convert_to_emulform(dumpdata) + + local outfile = io.open(output, "w") + if outfile == nil then + return oops("Could not write to file ", output) + end + + outfile:write(dumpdata:lower()) + io.close(outfile) + print(("Wrote an emulator-dump to the file %s"):format(output)) +end + + +--[[ +In the future, we may implement so that scripts are invoked directly +into a 'main' function, instead of being executed blindly. For future +compatibility, I have done so, but I invoke my main from here. +--]] +main(args) diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index 9cc865f0..77f36ae4 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -112,6 +112,8 @@ function mfcrack_inner() return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." elseif isOK == 0xFFFFFFFD then return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." + elseif isOK == 0xFFFFFFFC then + return nil, "The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." elseif isOK ~= 1 then return nil, "Error occurred" end diff --git a/client/util.h b/client/util.h index a57daf82..8a749ccb 100644 --- a/client/util.h +++ b/client/util.h @@ -47,6 +47,7 @@ char * printBits(size_t const size, void const * const ptr); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); char param_getchar(const char *line, int paramnum); +int param_getptr(const char *line, int *bg, int *en, int paramnum); uint8_t param_get8(const char *line, int paramnum); uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); diff --git a/common/cmd.c b/common/cmd.c index 0c3ecc1f..02257ac0 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -50,30 +50,32 @@ bool cmd_receive(UsbCommand* cmd) { } bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) { - UsbCommand txcmd; - for (size_t i=0; i + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + mbedtls_md_hmac_reset( &ctx->md_ctx ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( rounds == 2 ) + mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, K ); + + /* Step 2 or 5 */ + mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + } +} + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + mbedtls_hmac_drbg_update( ctx, data, data_len ); + + return( 0 ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + + seedlen = ctx->entropy_len; + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + mbedtls_hmac_drbg_update( ctx, seed, seedlen ); + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + + /* 4. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + size_t entropy_len, md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; + + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + + /* + * For initialisation, use more entropy to emulate a nonce + * (Again, matches test vectors.) + */ + ctx->entropy_len = entropy_len * 3 / 2; + + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + ctx->entropy_len = entropy_len; + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for reseeds + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + mbedtls_hmac_drbg_update( ctx, additional, add_len ); + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + mbedtls_md_hmac_reset( &ctx->md_ctx ); + mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + mbedtls_hmac_drbg_update( ctx, additional, add_len ); + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + + /* 8. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free an HMAC_DRBG context + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + { + fclose( f ); + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + mbedtls_hmac_drbg_update( ctx, buf, n ); + + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/common/hmac_drbg.h b/common/hmac_drbg.h new file mode 100644 index 00000000..eeac3e32 --- /dev/null +++ b/common/hmac_drbg.h @@ -0,0 +1,300 @@ +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + * + * Copyright (C) 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 MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct +{ + /* Working state: the key K is not stored explicitely, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization + * Makes the context ready for mbetls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or + * mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding + * Seed and setup entropy source for future reseeds. + * + * \param ctx HMAC_DRBG context to be seeded + * \param md_info MD algorithm to use for HMAC_DRBG + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \note The "security strength" as defined by NIST is set to: + * 128 bits if md_alg is SHA-1, + * 192 bits if md_alg is SHA-224, + * 256 bits if md_alg is SHA-256 or higher. + * Note that SHA-256 is just as efficient as SHA-224. + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * (For use with deterministic ECDSA.) + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \return 0 if successful, or + * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or + * MBEDTLS_ERR_MD_ALLOC_FAILED. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx HMAC_DRBG context + * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each reseed + * (Default: given by the security strength, which + * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) + * + * \param ctx HMAC_DRBG context + * \param len Amount of entropy to grab, in bytes + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) + * + * \param ctx HMAC_DRBG context + * \param interval Reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief HMAC_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (can be NULL) + * \param add_len Length of additional data (can be 0) + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param out_len Length of the buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, or + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, + * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or + * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/common/lfdemod.c b/common/lfdemod.c index 94e08ffa..71cbfea9 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1482,3 +1482,30 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) *size = numBits; return errCnt; } +// on successful return 1 otherwise return 0 +int VikingDecode(uint8_t *BitStream, + size_t size, + size_t *startIdx, + uint8_t *id_bits, + size_t id_bits_size) +{ + //no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future + // otherwise could be a void with no arguments + //set defaults + uint32_t i = 0; + uint32_t lastcheckindex = size - (id_bits_size * 2); + int found = 0; + while (i < lastcheckindex) + { + if (memcmp(BitStream + i,id_bits,id_bits_size) == 0) + { + *startIdx = i; + found = 1; + break; + } + i++; + } + return found; +} + + diff --git a/common/lfdemod.h b/common/lfdemod.h index d16aab9e..3b807b56 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -49,5 +49,6 @@ int IOdemodFSK(uint8_t *dest, size_t size); int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); int PyramiddemodFSK(uint8_t *dest, size_t *size); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); +int VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bit,size_t id_bits_size); #endif diff --git a/common/sha256.c b/common/sha256.c new file mode 100644 index 00000000..d5e70221 --- /dev/null +++ b/common/sha256.c @@ -0,0 +1,446 @@ +/* + * FIPS-180-2 compliant SHA-256 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-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +//#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(MBEDTLS_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (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) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; +} + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( W[i], data, 4 * i ); + else + R( i ); + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; +} +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +void mbedtls_sha256_update( mbedtls_sha256_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 ); + mbedtls_sha256_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_sha256_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha256_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-256 final digest + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +{ + 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 ); + + mbedtls_sha256_update( ctx, sha256_padding, padn ); + mbedtls_sha256_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 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); +} + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +void mbedtls_sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + mbedtls_sha256_starts( &ctx, is224 ); + mbedtls_sha256_update( &ctx, input, ilen ); + mbedtls_sha256_finish( &ctx, output ); + mbedtls_sha256_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + mbedtls_sha256_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + mbedtls_sha256_update( &ctx, buf, buflen ); + } + else + mbedtls_sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + + mbedtls_sha256_finish( &ctx, sha256sum ); + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/common/sha256.h b/common/sha256.h new file mode 100644 index 00000000..0dbc4b25 --- /dev/null +++ b/common/sha256.h @@ -0,0 +1,142 @@ +/** + * \file mbedtls_sha256.h + * + * \brief SHA-224 and SHA-256 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 MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-256 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} +mbedtls_sha256_context; + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-256 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); + +/* Internal use */ +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void mbedtls_sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/doc/RFID_Antenna-Basic-Form.stl b/doc/RFID_Antenna-Basic-Form.stl new file mode 100644 index 0000000000000000000000000000000000000000..6679ae8b5b72814e032869494007d8b69efecffc GIT binary patch literal 3084 zcmb7_L2eU45Jme8oWL7UR>+E2umCZ@2Be@!gag$PvO-zbBH=_;vSX_xa(+?)G;7cAua9e)skM?*8Y;d7l67{wqE-Ma)CJKeaYZt;Mmm z10HIQe9!r4JuVUNk|tsF6+(VbAdPkc+E&^n;`ga-5Lh`Q)YWssR?dhxj-8{!;-M9e zPHX;U1WBXep_6S0->o$3Q$J3v4UbCX%0fE<9VnbZlB?6yYb^xo_W9LAl!)pYb5029Afw{m+A?UG1fCkY6BT2e*A5KuKtKlI^MD-Az^Qg_}ol*Q5=g#p4e$1jS z9+(utdh&4kWrXM_co`jdL&(Ec`tIrH#N%>SmB7jwp{_s&9nvG#-IB1ZMd#^?!06{A z?Q{~Tt*$&vdvaoQ)w4k{Nc8voJ*Y{j5~{?y2NC+!L^}Zuq6bFS^DK5%J(55+Lj*lo z*9qHGAaj2G{nZ;}Fs!aL$LmD(Z~{75ctpP;(t}yr(*+{ViF#I|a~|1#`|zgb3Gm*P zJ{;E@eB8U0n5Jz4G&~d}S+9D~kMmh6kk1DpqI#&qm0(R#^57`#9+(Rx7lO66h_Q1x zbPtk#KJwsb|8_C5@!h>_W$8+O=}iLBI~#J*?(yxkR-%aFiV>6M#po)&xhFz5s<<65$@$4)QqeYlz0##s)y*6pc2*5^5q^Qvl9K?C?}vJ zmoPHZ&&Qy;^Q1&n50N>q?EFpKLt0%W=|t*WSvqtg_km1xa)Yy{*1t@j&$~V6<)IVK Kn|h1j-Tn{btXe<- literal 0 HcmV?d00001 diff --git a/doc/RFID_Antenna-With-Lanyard-Hook.stl b/doc/RFID_Antenna-With-Lanyard-Hook.stl new file mode 100644 index 0000000000000000000000000000000000000000..62f5397a8391cd0a0e2ae5c176d19bc13c44083b GIT binary patch literal 8484 zcmb7J&#Ps{5pE(AXBQ9>&=E5T83zI~41zzvxi7jgL=n_%vdBt87XAxD$$%&*hzn7Y z#hdt?8R3Qe2Xn{kk3b>>gph3(3hpG^Y?AM*s;|5Hoco^Iy!%eyuKMb$s;=&HPT%KW zc>0O+zj*$c^OrAQdhk;IUAlDs$!DK__PNKm+wK3(f3J44wRZF7nOnHDU;pFfO>1v_ z)SBUXeHVR7uJ6A7@--j-=T{%>npMOkadbtr7Kk5z^RaXM_UcQp{i@r#_q`9&Zff~> zYaDO(w||}6($YhB|7!E;)vJ#9(N7^MS~1?5j~g_%um9zX2Y}qX{fAc~4m;Xatr&+{ zj5mWf&H?YP{Q39hh|fNIe^<3)yfuzDLyjDQ3|xVc;ArpfCM_SQ?+e5&aXj|upAZMp zp(V7ByH|hw>$w}u*@)v>=b+Z`@EW{gUwY2kQ!-3z6j|!Zt+A9JQ|G z6)R3!UVRzgx~>$tOEM1jmBUe2^pJH`CCVtZ#yqL6KL5?R2Uu5CGG^^4XVW(8x>A); zqRMcsQg6KyGs~kA*L7u^QCA4VXHp!Lh-1_h*1xH){(JuyH&|CAj%$1B$~IG7c||H$ zlqgrDu52^vieAN99F@4PtC;_0&}K9IZCd*QDv)j7uVOs+F@u;NG$B$__N!5$u*9rl zefyq>+9d}OtakAo?%sIw4j=E;-Vu{zh0yw7b&w+>KjXHTlR&3d<9KV4D^?)CalPMn z<%f=lj1H|BZ!PA7yC?RNi=4rSFW>11&TZ9-ahUZvhd0i_mG$A@1HsCuS~1>Q)K%O! zbRRhz9N7CNt;TV-+!LLHSr$iB_|OtM)(5?Mv3^LzW)Y5FmeX!IOI8;~HXRTf_i%Q&sunq0b z9L1}xykd;uv)W4u57~U7=ELvRXzQM|*ti6$T06#?dn(r*`)te=`o=CkXhNi9LJ(aL zt{w>0F89Q7r>^^>?2BXUoHL?60Z?~%^ayMp9N_zH?7jG~&nv&@xHWHzp&}kiG!X@T z3PR|2fh_2XK)*=ZKEykb-Ij3_1SAteUab*DG9m1CL=F#Om(3%$DJMNz@_j!9c?&n~ zmU^nus!#juzje@Bc(p{Nq{mSa=z~LzNJC6RL9WWj zJ}u#D_`g7;WG^BjZ)}MqJL9Mv?8~d*=pKQqNIHkm!z(a^XYAnFnG#+vf=~To$sk4Z zSa`kNBb?CR4I%Wq;40jPZ)oBulFnBVZ;jezhS@R>NG6250@_@!&xxWXqGauB53O*L`3e^6It^k4qnUM4w^j=wANXbBB%HhHD~ah?b(@>u6_isOJlH0>YpPCn4nNwHxZALp15WAEae zvt>+%-qr{FAG6D*Xye;5@+G3?XNkafOOJ3psgaK@Jl}^%NvPp}MWAmfz?GVcBS-s1 z)q??O3MIsnL$Dkt0xhDC>eE?hJwYhkM)gGC%4*LO)8b*Q51orrLmU+`^PRxa^y@;yRYeRB`5aWx&}Libsv;D5f4%s(=W3F4uZU1x6~u<)6^H O3=Fu$Cdpm|koJEJ#e`%4 literal 0 HcmV?d00001 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 353c6120..96e5e5a2 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -98,6 +98,8 @@ typedef struct{ #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 +#define CMD_VIKING_CLONE_TAG 0x0222 + /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ -- 2.39.2